Freitag, 8. Mai 2015

Yes, you can test it (1) - Prerequisites

Before you start with unit testing, you must fulfill one prerequisites ... you need to create a unit. Sounds logic, but what does this mean?


In OOP, all classes are connected to each other in some way. If there is a class without any coupling, it is either the god-object-all-in-one-main-class or you can delete it. You need to decouple these dependencies to make sure, another class does not have any unexpected effect on the class you want to test. Therefore you need to create an interface for each f***ing class, unless it is a pure data object (a DTO or POCO).

This results in a lot of constructor and property injection with interfaces to be able to mock or fake these dependencies. A mock has exactly the behavior you define in your test. It does not have any side effects, or a dependent dependency which causes an unexpected behavior.

What do you need to do with your code?

Lets assume you have the following code:
public class Foo
{
    public void DoSomething()
    {
        // coupled to EmailSender
        var sender = new EmailSender();
        sender.Send("Whatever");
    }
}
You have a dependency to EmailSender. To refactor the class without any breaking changes, you must ensure, the default behavior of class Foo still uses EmailSender, but you are able inject your own mock with an expected behavior. Thanks to C# 4 and default parameter, it is very simple: Use a constructor with a default parameter and extract an interface for EmailSender.
public class TestableFoo
{
    private readonly IEmailSender _sender;
    public TestableFoo(IEmailSender sender = null)
    {
        _sender = sender ?? new EmailSender();
    }
    public void DoSomething()
    {
        _sender.Send("Whatever");
    }
}
public interface IEmailSender
{
    void Send(string message);
}
This code does not produce any breaking changes, but you can mock IEmailSender and define a predictable behavior for Send().

This is the first step you need to do with a class you want test with unit tests. The great benefit is that you can do this on every brownfield project and refactor and test your code class by class.

Think big, start small.

Keine Kommentare:

Kommentar veröffentlichen