Recently
I've been working with Test Driven Development (TDD) and FakeItEasy. Test
Driven Development is a test-first approach to developing software and
FakeItEasy is a mocking framework. Using TDD and FakeItEasy together can help
you build maintainable, loosely coupled solutions. Here are some of the key TDD
principles:
- Write a
failing unit test first.
- Write the
minimum code needed to get the test to pass.
- Refactor
code to acceptable standards.
- Use a
mocking framework to test external dependencies.
Here are
some of the benefits I’ve experienced recently using Test Driven Development
and FakeItEasy:
- Writing
unit tests first helps drive the design of the project; it makes the solution
more component based.
- Mocking
objects helps you build Interface based components that support dependency
injection.
- Test
Driven Development helps you understand the requirements and the acceptance
criteria for each use case/ user story.
- Unit
tests – with descriptive names – can provide valuable system documentation.
Here's an example of how to use FakeItEasy:
Step 1: Open Visual Studio. Add three class library projects to your solution:
-- DataService
-- Tests.IntegrationTests
-- Tests.UnitTests
Step 2: Right-click project “Tests.UnitTests”. Select “Manage NuGet Packages”:
-- Install-Package NUnit
-- Install-Package FakeItEasy
-- Add a new class called “When_calling_fake_data_service.cs”
Step 3: Add two unit tests to class When_calling_fake_data_service.cs. These tests won’t pass yet.
[Test]
public void Should_call_GetOrders()
{
// Arrange
var fakeDbClient = A.Fake<IDbClient>();
// Create system under test
var service = new DAL(fakeDbClient);
// Act
service.GetOrders();
// Assert
A.CallTo(()
=> fakeDbClient.GetOrders()).MustHaveHappened();
}
[Test]
public void Should_get_fake_orders()
{
// Create a fake expected
response
var expectedData = new List<Order>
{
new Order()
{OrderId = 100, Description = "desc
100"},
new Order()
{OrderId = 200, Description = "desc
200"},
new Order()
{OrderId = 300, Description = "desc
300"}
};
// Arrange
var fakeDbClient = A.Fake<IDbClient>();
// Tell FakeItEasy to return
fake response when GetOrders is called
A.CallTo(()
=> fakeDbClient
.GetOrders())
.Returns(expectedData);
// Create system under test
var service = new DAL(fakeDbClient);
// Act
var result = service.GetOrders();
// Assert
Assert.AreEqual(expectedData,
result, "Incorrect
result from GetOrders!");
}
Step 4: Select project “DataService”. Add the following code to class “DAL.cs”:
public class Order
{
public int OrderId { get; set; }
public string Description { get; set; }
}
public interface IDbClient
{
List<Order>
GetOrders();
}
public class DAL
{
private readonly IDbClient _db;
public DAL(IDbClient db)
{
_db = db;
}
public List<Order>
GetOrders()
{
return _db.GetOrders();
}
}
public class DbClient : IDbClient
{
public List<Order>
GetOrders()
{
var lstOrders = new List<Order>
{
new Order()
{OrderId = 1, Description = "desc
1"},
new Order()
{OrderId = 2, Description = "desc
2"},
new Order()
{OrderId = 3, Description = "desc
3"}
};
return lstOrders;
}
}
Step 5: Run both unit tests – they should pass now.
So what? What did we learn/ achieve?
- FakeItEasy enables developers to test modules in isolation.
- Creating interfaces is a best practice – it’s the first step towards mocking external systems.
- Writing unit tests first helps developers to understand requirements and build component based systems.
- Unit tests – with descriptive names – can provide valuable system documentation.
For more info check out:
http://pluralsight.com/ - Test First Development Part I & II
https://github.com/FakeItEasy/FakeItEasy/wiki
http://en.wikipedia.org/wiki/Test-driven_development
http://en.wikipedia.org/wiki/Unit_testing