I’ve been busy retrofitting tests to a legacy system. We think our current best bang-for-buck are integration tests, at a service layer since there is plenty of state, lots of valueobjects and most of the interesting business behaviour cross cuts several services. We’ve been trying to build up a suite of test assitants in the form of Builder/Factories yet most unit tests don’t offer much value because the way the services interact with each other (a code smell yes, but will remain for a while given the sheer amount of it).
Instead, we’ve been wrapping service methods in a more convenient wrapper class to take the noise out of the extremely chatty APIs, wrapping away logic in something that we will call xxxServiceScenario. Just as Mark has been playing around with GetBuilderFor on his projects, we’ve hung out all of our specific service wrappers off a class called Scenario.
We then pass builders into scenarios to create the different test state that we need before calling a particular service to test its behaviour. The benefits of this approach include that it’s a bit clearer to users what we’re testing (anything associated with a Scenario is part of a GIVEN block), and we can choose to change the implementation (we’ve moved from using SQL to delegating to a service once we had more confidence in those services working properly) and our test methods are shorter without resorting to setup methods.
An example test might look like:
[Test] public void ShouldDoSomethingInterestingGivenAParticularScenario() { User firstUser = Scenario.Users().CreateMeARealUser(new UserBuilder().Build()); User secondUser = Scenario.Users().CreateMeARealUser(new UserBuilder().Build()); Scenario.Settings().EstablishDefaults(firstUser); Event onLineEvent = EventBuilder.For(firstUser).ViewedFrom(secondUser).Build() new InterestingService().ReactToInterestingEvent(onLineEvent); // some assertions here. ... }
Some developers seem to be liking this concept, so thought I’d share it to learn what we’ve been doing.