Using SpecFlow, we have made calls to our API service layer which then talks to the persistence layer. Most of our scenarios are covered nicely using the API to setup the database into different states, however there are a couple of scenarios which are not possible to get the database into via the API as they are failure states.
We were thinking we could create a layer which the SpecFlow solution talks to, which in turn "fudges" the database into that state so that we can then call the API layer to check we get the expected response. However is this correct in terms of BDD? My understanding of BDD is its very similar to ATDD where you test your main happy paths and exception paths and the fine grain stuff should be unit tested.
If you can't do something through the API, should it not be tested in your BDD scenarios?
I don't see any problem with doing this.
In fact your Given
steps should be able to do what is neccessary to get the system under test setup as your test needs it. What you are testing is the When
and validating it with the Then
.
If these given steps are always able to do the setup via the API then great, you get good test coverage of both, but there may be situations (as you have described) where you can't easily get the system into the desired state using the API. In this case you might have your given steps insert directly into the database, or call some testing service to set up the state.
You may also find that you need to do a similar thing with your Then
steps, if the results of your action are not publicly visible through the API.
You might also find that actually calling your API is too slow or long winded to do the setup you need (especially for complicated workflows) and so you may choose to insert data directly into the database in your given steps so that your tests are quicker and don't need to go through such complicated setup.
Be aware though that this has a cost itself in that if your database schema changes then you might need to update the API implementation AND update the steps which insert the data directly.
Whether this cost is worth bearing is something you'll have to decide.