Showing posts with label autofixture. Show all posts
Showing posts with label autofixture. Show all posts

Saturday, March 12, 2016

How I Learned to Love Loosely Coupled Test Data

"Play fast and loose with faith? So jest with heaven,
Make such unconstant children of ourselves"
-- Shakespeare, King John
Act III, Scene I, Lines 242-243

For C# development, I love to use AutoFac!  I find that AutoFac allows me to change the design of my code without having to worry about decencies.  The last thing I want to have to do while refactoring my design is fix a bunch of broken unit tests.  Typically if find that I have to support hard coded test setup for the system under test, when I change the signature of the constructor I'll also need to change all the test setups related to the class (this is often the case in code in which I was not the original author).  This can become very annoying, since the test cases often do not really care about the setup of the system under test.

If you are using a decency injection framework like AutoFac you really need to pair the loose coupling of your production code decencies with loose coupling of the setup of your system under test.  Loose coupling of the setup of your system under test is exactly what a test fixture is for.

Personally I love AutoFixture for C# development!  AutoFixture does all the hard work of creating a test fixture for you, all you have to do is walk up to it and ask it for what you want.

If you are using AutoFac or some other IoC framework in your system under test, more likely than not, you are using a mocking framework like Moq or Rhino Mocks.  Well, AutoFixture has you covered by allowing you to use an auto mocking plugin for Moq, Rhino Mocks, or whatever.  By using auto mocking along with AutoFixture you are able to create a system under test with all the decencies already mocked out.

With AutoFixture creating the system under test for you, you can freely change the signature of your constructor for your system under test without the need to change any of the setup for the test cases!

Say we have the following:



The above is a fairly common example of C# application that I work with.

We see that we are testing using two different test classes, one using AutoFixture and one not.  If we uncomment out the ILog decency in the System class we would break the test setup in the test class ProgramTestsWithoutAutoFixture, but the test class SystemTestsWithAutoFixture would continue to work!  For such a simple example this might not matter, but with larger code bases this can become an issue.

By using AutoFixture with Moq we are pairing the same loosely coupling of the creation of our system under test with the loosely coupling we get for our decencies in our production code using AutoFac.  Truly one can say, AutoFac iff AutoFixture with Moq.

Sunday, December 13, 2015

Round and Round We Go OR How to Stop Circular References in AutoFixture

"That many things, having full reference"
-- Shakespeare, Henry V
Act I, Scene II, Line 205

I love to use AutoFixture to setup the the arrange part of my tests.  I find that working without worrying about the arrange allows me to focus more on the task at hand.  A possible downside of working this way is that AutoFixture is mindlessly setting up all the test data.

Having AutoFixture setup your test data is fine when working with green field classes but when working with legacy code and third party code you getting into cases in which you have circular references.  What do I mean?  Compare the following:

Case 1:

class A has members with type B
type B has member with type C
type C is a primitive

Case 2:

class X has members with type Y
type Y has member with type Z
type Z has member with type X

In case 1 we have a termination point with type C, AutoFixture can happily go about and create an instance of A and populate all the members in the hierarchy with data.

In case 2 we do not have a termination point, Z has a member of type X which a member of type Y which a member of type Z which goes back to X and so on.  Case 2 has a circular reference and AutoFixture is unable to give us back an instance of X without going into an endless loop.  Luckily AutoFixture is smart enough to figure out that it is in an endless loop and will error out telling us about the issue.

What do we do if we have a class like X in legacy code or third party code?  We'll we can tell AutoFixture that we will have classes like X but that it is fine to just terminate the repeating hierarchy with a null or empty.  We use the following to do that:



I normally put this in my TestInitialize for the test class of the offender, but I can see putting in the arrange of a test class if you are mixing old and new.  There you have it, a way to use AutoFixture with dirty old classes.


Sunday, December 6, 2015

AutoFixture for the Win

"What have I kept back?"
-- Shakespeare, Antony and Cleopatra
Act V, Scene II, Line 147.2

Anyone who has paired with me while working in C# knows that I am addicted to AutoFixture.  Now I do not try to add it to everything that I am working, but usually it finds its way into whatever I am working on.  Why?  Simply put, using AutoFixture allows me to focus on the task at hand.

Here is a quick example:



In this example I am implementing the higher order function Map using the higher order function Fold (see my other post if this interested you).

What do you not see in the tests?  The setting up of the test data.

Why?  It is not important to the task at hand.  We do not need it to test the behavior of Map.  Map takes a collection and a function and applies the function against every member of the collection producing a new collection.  What we want to verify is the applies part, which only requires a collection and a function, the actual members of the collection (and the function) do not matter for this verification.

Staying focus on the task at hand is the power of a test fixture and having someone else implement the test fixture for you is even better.  Using AutoFixture with xUnit you really do not need to think about setting up test data at all and that is good thing.