Behat/Behat — Issue #58: Support testing for expected exceptions
Author: acoulton
Created: 2011-10-08 10:23:52+00:00
State: open

For testing APIs in particular, it would be helpful to be able to test that a given action throws a particular exception.

For example, a scenario similar to this:

Scenario: Trying to access protected fields without authentication generates an exception
Given I have a new API object
Then I should catch an AccessDeniedException when I access the email property
And the exception message should contain "foo"

The most obvious and reusable way to achieve this would be to chain a step from the "Then I should catch..." definition.

However, after playing around for a while, I can't see a way to implement this in the current architecture. Obviously the existing step chaining won't work because in that case the chained step would fail and so would the scenario. I thought about implementing a hook, but they seem to be able only to read the scenario/step results rather than being able to change them.

I think the best approach would be to support executing a substep directly within a FeatureContext - something like this:

```php
/**
* @Then /^I should catch an ([a-zA-Z_]+) when (.+)$/
*/
public function iShouldCatchAnException($exception_type, $when_step)
{
// Execute the action
$step = new When($when_step);

try
{
// Execute Step
}
catch (\Exception $e)
{
// Test for the expected type and store or rethrow
}
}
```

However, I don't think that's possible at present because the FeatureContext doesn't have a reference to either the StepTester or the DI container, so it's not even able to duplicate the StepTester logic as it can't access the definitions.

I'm not sure the best way to resolve this, but I don't think it's possible without changing the core to pass in one or other of those dependencies to the FeatureContext method somehow? I'm happy to have a go at doing so if you agree that this would be a useful scenario to be able to support?

Otherwise, I think the only option would be to specifically define individual steps, which is fairly brittle and would probably cause duplication especially since often you'll want to test that an exception is thrown from a method that you are anyway testing in non-exception use cases - it would be nice to be able to share that definition.