Unit Testing DateTime – The Crazy Way

We all know that the process of unit testing code that depends on DateTime, particularly the current time provided through the static properties (Now, UtcNow and Today), it’s a PITA.

If you go ask how to unit test DateTime.Now on stackoverflow I’ll bet that you’ll get two kind of answers:

  1. Encapsulate the current time in your own interface and use a standard mocking framework;
  2. Pull out the big guns like Typemock Isolator, JustMock or Microsoft Moles/Fakes and mock the static property directly.

Now each alternative has is pros and cons and I would have to say that I glean more to the second approach because the first adds a layer of abstraction just for the sake of testability. However, the second approach depends on commercial tools that not every shop wants to buy or in the not so friendly Microsoft Moles. (Sidenote: Moles is now named Fakes and it will ship with VS 2012)

This tends to leave people without an acceptable and simple solution so after reading another of these types of questions in SO I came up with yet another alternative, one based on the first alternative that I presented here but tries really hard to not get in your way with yet another layer of abstraction.

So, without further dues, I present you, the Tardis. The Tardis is single section of conditionally compiled code that overrides the meaning of the DateTime expression inside a single class. You still get the normal coding experience of using DateTime all over the place, but in a DEBUG compilation your tests will be able to mock every static method or property of the DateTime class.

An example follows, while the full Tardis code can be downloaded from GitHub:

using System;
using NSubstitute;
using NUnit.Framework;
using Tardis;

public class Example
{
    public Example()
        : this(string.Empty) { }

    public Example(string title)
    {
#if DEBUG
        this.DateTime = DateTimeProvider.Default;
        this.Initialize(title);
    }

    internal IDateTimeProvider DateTime { get; set; }

    internal Example(string title, IDateTimeProvider provider)
    {
        this.DateTime = provider;
#endif
        this.Initialize(title);
    }

    private void Initialize(string title)
    {
        this.Title = title;
        this.CreatedAt = DateTime.UtcNow;
    }

    private string title;

    public string Title
    {
        get { return this.title; }
        set
        {
            this.title = value;
            this.UpdatedAt = DateTime.UtcNow;
        }
    }

    public DateTime CreatedAt { get; private set; }
    public DateTime UpdatedAt { get; private set; }
}

public class TExample
{
    public void T001()
    {
        // Arrange
        var tardis = Substitute.For<IDateTimeProvider>();
        tardis.UtcNow.Returns(new DateTime(2000, 1, 1, 6, 6, 6));

        // Act
        var sut = new Example("Title", tardis);

        // Assert
        Assert.That(sut.CreatedAt, Is.EqualTo(tardis.UtcNow));
    }

    public void T002()
    {
        // Arrange
        var tardis = Substitute.For<IDateTimeProvider>();
        var sut = new Example("Title", tardis);
        tardis.UtcNow.Returns(new DateTime(2000, 1, 1, 6, 6, 6));

        // Act
        sut.Title = "Updated";

        // Assert
        Assert.That(sut.UpdatedAt, Is.EqualTo(tardis.UtcNow));
    }
}

This approach is also suitable for other similar classes with commonly used static methods or properties like the ConfigurationManager class.

Advertisements

Unit Testing with NUnit and Moles Redux

Almost two years ago, when Moles was still being packaged alongside Pex, I wrote a post on how to run NUnit tests supporting moled types.

A lot has changed since then and Moles is now being distributed independently of Pex, but maintaining support for integration with NUnit and other testing frameworks.

For NUnit the support is provided by an addin class library (Microsoft.Moles.NUnit.dll) that you need to reference in your test project so that you can decorate yours tests with the MoledAttribute. The addin DLL must also be placed in the addins folder inside the NUnit installation directory.

There is however a downside, since Moles and NUnit follow a different release cycle and the addin DLL must be built against a specific NUnit version, you may find that the release included with the latest version of Moles does not work with your version of NUnit.

Fortunately the code for building the NUnit addin is supplied in the archive (moles.samples.zip) that you can found in the Documentation folder inside the Moles installation directory. By rebuilding the addin against your specific version of NUnit you are able to support any version.

Also to note that in Moles 0.94.51023.0 the addin code did not support the use of TestCaseAttribute in your moled tests. However, if you need this support, you need to make just a couple of changes.

Change the ITestDecorator.Decorate method in the MolesAddin class:

Test ITestDecorator.Decorate(Test test, MemberInfo member)
{
    SafeDebug.AssumeNotNull(test, "test");
    SafeDebug.AssumeNotNull(member, "member");

    bool isTestFixture = true;
    isTestFixture &= test.IsSuite;
    isTestFixture &= test.FixtureType != null;

    bool hasMoledAttribute = true;
    hasMoledAttribute &= !SafeArray.IsNullOrEmpty(
        member.GetCustomAttributes(typeof(MoledAttribute), false));

    if (!isTestFixture && hasMoledAttribute)
    {
        return new MoledTest(test);
    }

    return test;
}

Change the Tests property in the MoledTest class:

public override System.Collections.IList Tests
{
    get
    {
        if (this.test.Tests == null)
        {
            return null;
        }

        var moled = new List<Test>(this.test.Tests.Count);

        foreach (var test in this.test.Tests)
        {
            moled.Add(new MoledTest((Test)test));
        }

        return moled;
    }
}

Disclaimer: I only tested this implementation against NUnit 2.5.10.11092 version.

Finally you just need to run the NUnit console runner through the Moles runner. A quick example follows:

moles.runner.exe [Tests.dll] /r:nunit-console.exe /x86 /args:[NUnitArgument1] /args:[NUnitArgument2]

Introducing NFakeMail

Ever had to resort to custom code to control emails sent by an application during integration and/or system testing? If you answered yes then you should definitely continue reading.

NFakeMail makes it easier for developers to do integration/system testing on software that sends emails by providing a fake SMTP server. You’ll no longer have to manually validate the email sending process. It’s developed in C# and IronPython and targets the .NET 4.0 framework.

With NFakeMail you can easily automate the testing of components that rely on sending mails while doing its job. Let’s take a look at some sample code, we start with a simple class containing a method that sends emails.

class Notifier
{
    public void Notify()
    {
        using (var smtpClient = new SmtpClient("localhost", 10025))
        {
            smtpClient.Send("me@me.com", "you@you.com", "S1", ".");

            smtpClient.Send("me@me.com", "you@you.com", "S2", "..");
        }
    }
}

Then to automate the tests for this method we only need to the following:

[Test]
public void Notify_T001()
{
    using (var server = new FakeSmtpServer(10025))
    {
        new Notifier().Notify();

        // Verifies two messages are received in the next five seconds
        var messages = server.WaitForMessages(count: 2, timeout: 5000);

        // Verifies the message sender
        Debug.Assert(messages.All(m => m.From.Address == "me@me.com"));
    }
}

The created FakeSmtpServer instance will act as a simple SMTP server and intercept the messages sent by the Notifier class. It’s even possible to verify some fields of each intercepted message and by default all intercepted messages are saved to the file system in MIME format.

Do Repeat Yourself in Unit Tests

Don’t get me wrong I’m a big supporter of the DRY (Don’t Repeat Yourself) Principle except however when it comes to unit tests. Why? Well, in my opinion a unit test should be a self-contained group of actions with the intent to test a very specific piece of code and should not depend on externals shared with other unit tests.

In a typical unit test we can divide its code in two major groups:

  • Preparation of preconditions for the code under test;
  • Invocation of the code under test.

It’s in the first group that you are tempted to refactor common code in several unit tests into helper methods that can then be called in each one of them. Another way to not duplicate code is to use the built-in infrastructure of some unit test frameworks such as SetUp/TearDown methods that automatically run before and after each unit test.

I must admit that in the past I was guilty of both charges but what at first seemed a good idea since I was removing code duplication turnout to offer no added value and even complicate the process when a given test fails.

We love unit tests because of their rapid feedback when something goes wrong. However, this feedback requires most of the times reading the code for the failed test. Given this, what do you prefer? To read a single method or wander through several methods like SetUp/TearDown and private common methods.

I say it again, do repeat yourself in unit tests. It may feel wrong at first but I bet you won’t regret it later.

Unit Testing With NUnit and Moles

UPDATE: For a revisited version of integrating Moles with NUnit check:

Unit Testing With NUnit And Modes Redux.


Moles is a lightweight detour framework that lets you replace any .NET method (including static methods) with your own delegate.

The latest version of Microsoft Pex brought some very interesting improvements. Amongst them and the one that got me most curious was the support for using Moles with NUnit tests.

When writing unit tests is common to have tests with external dependencies not relevant to the behaviour under test. Using mocking frameworks you can get around these situations but the most popular ones like Rhino Mocks and Moq, as far as I know, cannot mock sealed types or static methods. Typemock however places no constraints but is not free.

With Moles you have greater flexibility and the delegate based approach is also easy to read and understand as you can see in the next example:

[Test]
[Description(
    @"An exception SHOULD be thrown if the default value
    is not valid for the associated option definition type."
    )]
public void Constructor_T008()
{
    MOptionType optionType = new MOptionType();

    optionType.NameGet = () => "OptionTypeMock";
    optionType.CanChangeDefaultValueGet = () => true;
    optionType.MinValuesCountGet = () => 1;
    optionType.MaxValuesCountGet = () => 1;
    optionType.ValidateValueObject = x => false;

    Assert.Throws(() => {
        new OptionDefinition(optionType, "Name", "NonBooleanValue");
    });
}

In the previous code snippet I configure a mole for an OptionType instance to return false in the method ValidateValue allowing me to test that the OptionDefinition constructor reacts in a proper way when the provided argument is an invalid value.

Since Moles needs the Pex profiler to work, you have to run this NUnit test using Pex command line runner with NUnit console.

Example:
pex /runner:D:\TOOLS\nunit-console.exe Parser.UnitTests.dll

Unit Test Naming Conventions

When I started writing unit tests I followed the standard of stating the behavior under test in the name of the test method. It was something like what Roy Osherove talks about in this 2005 post and has the following format:

[MethodName_StateUnderTest_ExpectedBehavior]

It worked reasonably well most of the cases, but sometimes, probably due to an effort in maintaining the name within a reasonable length the results were less than satisfying or I would spend too much time trying to get the name right.

Having decided to try a different approach I searched the web looking to find out how others were tackling this situation and what unit test naming guidelines they were using. In general it would all come to the same descriptive method name until I found a very interesting read in this post by Jay Fields. He compares test names to glorified comments and talks about anonymous tests.

Completely anonymous tests would be something of an extreme measure for me and the unit test framework being used doesn’t even support it (NUnit). However it kind of inspired me to try my own simplified approach which ended up like this:

[MethodName_TestID]

and where each test method has an associated description clearly stating the behavior under test. This way the method name remains concise and in the case of a test failing I rely on the test runner report (Gallio) to include the associated description thus allowing to quickly understand what went wrong.

Gallio Failed Test Report
Gallio Failed Test Report

Throw in a visual studio snippet to quickly define a new unit test with the custom format and we are ready to go.