- Notifications
You must be signed in to change notification settings - Fork1
Leaping Gorilla's testing framework for BDD style Given/When/Then without the ceremony
License
LeapingGorillaLTD/Testing
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
LeapingGorilla.Testing is an attribute based framework for BDD style Given/When/Then unit testing without the ceremony.
The LeapingGorilla.Testing is now available on NuGet. Get it using:
PM>install-package LeapingGorilla.Testing
or if you prefer XUnit:
PM>install-package LeapingGorilla.Testing.XUnit
We at Leaping Gorilla strive to remove as much friction as possible from our testing methodology. To that end we wanted a drop dead simple way to create unit tests that adhered to a few core principles:
- Must support constructor-based dependency injection
- Must have the ability to automatically mock any dependencies we wish to use with our item under test
- Must have the ability to override automatic mocking should the need arise
- Must support a clean syntax for stubbing method calls on our dependencies
- Must have a clean BDD style Given/When/Then flow
From these needs LeapingGorilla.Testing was born.
LeapingGorilla.Testing builds on the shoulders of giants. We useNUnit as our core testing framework,NSubstitute performs mocking duties andFast-member provides quick reflective access to members on our classes. We also have a version which builds onXUnit rather than NUnit should that be your favoured framework.
Enough of the introductions, lets look at how it works.
publicclassWhenTestingStubbing:WhenTestingTheBehaviourOf{[ItemUnderTest]publicClassRaisingAnEventClassRaisingEvent{get;set;}[Dependency]publicIMockEventRaiserEventRaiser{get;set;}privatestring_severeResponse;privatestring_severeReturn;[Given]protectedvoidTheEventRaiserHasSevereResponse(){_severeResponse="This is a severe response";EventRaiser.RaiseEvent(true).Returns(_severeResponse);}[When]protectedvoidTheEventRaiserRaisesASevereEvent(){_severeReturn=ClassRaisingEvent.DoSomethingWithTheEventRaiser(true);}[Then]publicvoidSevereReturnShouldMatchResponse(){Assert.That(_severeReturn,Is.EqualTo(_severeResponse));}[Then]publicvoidEventRaiserShouldBeCalled(){EventRaiser.Received(1).RaiseEvent(Arg.Any<bool>());}}
Here you can see the attribute led style that LeapingGorilla.Testing uses to make testing painless. We start with the concept of anItemUnderTest
. This is the concrete instance that the framework will create for us. This concrete instance has dependencies injected via the constructor - in this case anIMockEventRaiser
. We mark a property of this with aDependencyAttribute
and we're good to go.
LeapingGorilla.Testing starts by locating all of our Dependencies, creating a mock of each and loading them into the test class. Next it finds the item under test, finds the constructor that best matches our dependencies and then creates an instance of the item under test passing the dependencies into the constructor and loads it into the test class.
From here we look for any methods marked with aGivenAttribute
. You can have as many Given methods as you want (zero, one or more). LeapingGorilla.Testing will find and execute each in turn. The order it will do so is undefined so if you need to be specific on the order that we call them use the optional Order property like:
[Given(Order=1)]
You should use yourGiven
methods to setup your stubbing in dependencies. We leverage NSubstitute for this so take a look atthe NSubstitute website. With our given methods executed the framework then finds your optionalWhen
method. You may have zero or one method marked with aWhenAttribute
. If one is found it will be called and at this point we hand over to the NUnit framework to assert each of yor test cases.
NUnit will find all public methods marked with aThenAttribute
and run each of them as an individual test. It's best practice to avoid modifying any state in yourThen
tests - you can't guarantee the order they will run in so it's easy to trip yourself up.
- Create a new test class inheriting from
WhenTestingTheBehaviourOf
- Add a property to the class you want to test, mark it with an
ItemUnderTest
attribute - If your item under test has any dependencies to inject in the constructor, add a property for each with a
Dependency
attribute. - If you need to do any test setup (stubbing dependency methods, preparing input parameters or expected output parameters) create a method to do so and mark it with a
Given
attribute. To make life easier you can split your setup into multipleGiven
methods for readability. - If your test needs to call any functionality on your item under test create a method to do so and mark it with a
When
attribute. - Create as many public void methods as necessary to assert that your item under test has performed as expected. Mark each with a
Then
attribute and add whatAssert
statements you need.
A: Override theCreateManualDependencies
method and assign them from there
A: Mark it with aMock
attribute
A: Convention. At Leaping Gorilla we stick to the rule that each test class tests a single behaviour. If a behaviour can't be expressed as a single "When I X" then we take it as a sign that our code probably needs refactoring.
A: Use the optionalOrder
property at the point of decoration like:
[Given(Order=2)]
A: The short answer is: You can't. The longer answer is: you can override theCreateManualDependencies
method and substitute your own mock object there but we cannot generate an automatic mock. This is down to the nature of the .Net framework and short of using an expensive tool like TypeMock or JustMock itisn't going to change. Take it instead as an opportunity to do some glorious refactoring to break that concrete dependency into an interface.
A: Make sure that your method returns Task, not void and it will Just Work (tm) like:
[When]publicasyncTaskSomethingAsyncHappens(){_result=awaitMyAsyncThing();}
A: Fork and submit a pull request! For your pull request to be considered it should include tests as well as functional code.
A: LeapingGorilla.Testing is made available under theApache 2.0 License. You are free to use the software in any way you choose as long as you adhere to the license.
A: We are open to talk with you or your business! Drop us a line via ourcontact form.
About
Leaping Gorilla's testing framework for BDD style Given/When/Then without the ceremony