The problem with unit tests is that they keep on breaking…Obviously that’s not entirely correct, nevertheless I had the pleasure of hearing the sentence above numerous times. It’s true – unit tests do tend to fail and we prefer that they fail only when a regression occurs – when something that used to work stopped working, because that’s the reason they’re there in the first place.
The problem is that there are several instances when a test stops compiling due to requirement change or refactoring. consider the following test code:
[Test]
public void Add_AddTowNumbersInCalculator_ReturnResult()
{
var fakeDataAccess = Isolate.Fake.Instance<dataAccess>();
Isolate.WhenCalled(() => fakeDataAccess.Save(null)).WillReturn(true);
var customer = new Customer(fakeDataAccess);
//...
var result = customer.Save();
Assert.That(result, Is.True);
}
Simple. Now what happens when we need to change the Customer c’tor? – let’s say that it was decided that every customer should have a valid address the developer implement that requirement – like this:
[Test]
public void Add_AddTowNumbersInCalculator_ReturnResult()
{
var fakeDataAccess = Isolate.Fake.Instance<dataAccess>();
var fakeAddress = Isolate.Fake.Instance<Address>();
Isolate.WhenCalled(() => fakeDataAccess .Save(null)).WillReturn(true);
var customer = new Customer(fakeAddress, dataAccess);
//...
var result = customer.Save();
Assert.That(result, Is.True);
}
What if I already wrote a few dozen tests – what can I do?
- Create overloaded c’tor one with parameter and one parameterless
- Add a default value to the c’tor (.NET 4.0)
- Write all of the tests again – from scratch
- Delete your tests and never attempt unit testing your code ever again
- Create a factory method to instantiate Customer at your tests
- Quit your job and move to another country
In fact on my team this problem (needing to fix a lot of tests each time the c’tor signature change) was so severe that one of the developers took it upon himself to create a class that creates object just for the test with all of the parameters faked.
Luckily there is another way: the new Isolator V7 that was released a few weeks ago and one new feature got me exited (no not the auto-test-runner) – it’s The new API calls: Isolate.Fake.Dependencies and Isolate.GetFake.
Using the new API I’ve fixed the test to work like this:
[Test]
public void Add_AddTowNumbersInCalculator_ReturnResult()
{
var customer = Isolate.Fake.Dependencies<Customer>();
var fakeDataAccess = Isolate.GetFake<DataAccess>(customer);
Isolate.WhenCalled(() => fakeDataAccess.Save(null)).WillReturn(true);
//...
var result = customer.Save();
Assert.That(result, Is.True);
}
I just tell Isolator to fake all dependencies and “grab” the only one that interest me at this test and change it’s behavior – simple.And now my test won’t break due to c’tor changes.
Happy coding…
No comments:
Post a Comment