jimmy keen

on .NET, C# and unit testing

How to mock private method – solutions

January 25, 2015 | tags: unit-testing mocking c# design

I one of my previous blog entries I explained why it is not possible to mock private methods with tools like Moq or FakeItEasy. In this post I’ll show how you can overcome such situation1.

Problem: Origins

First, it is important to identify source of the problem. When you say “I need to mock this private method” you are essentially saying “Design of this class is terrible”. Properly designed SOLID code will never put you in a position which will require you to do private mocking. Source of the problem? Bad design.

To better understand my point let’s take a quick look at a class building order XML. Suppose you want to test CreateDocument method:

public class OrderDocumentFactory
{
    public XDocument CreateDocument(Order order)
    {
        var document = new XDocument();
        document.Add(new XElement("Order",
            new XElement("Date", order.Date.ToShortDateString()),
            new XElement("OriginalValue", order.TotalValue),
            new XElement("Discount", CalculateDiscount(order))
        ));

        return document;
    }

    private double CalculateDiscount(Order order)
    {
        var promotionsFileName = string.Format("P_{0:ddMMyy}.TXT",
            order.Date);
        var promotionsFileContent = File.ReadAllText(promotionsFileName);
        var baseDiscount = double.Parse(promotionsFileContent);
        var isLateProcessing = (DateTime.Now - order.Date).TotalDays > 3;
        var bonusDiscount = isLateProcessing ? 10.0 : 0.0;
        var totalDiscount = baseDiscount + bonusDiscount;

        return order.TotalValue * (100 - totalDiscount) / 100.0;
    }
}

CreateDocument is trivial to test if we can mock this discount calculation thing as it really gets in our way with all those file-loading, date-parsing and what-not. This is a lot of stuff we do not really care about, we should mock it. But we cannot. What to do then?

Design considerations

Single responsibility principle, first of the SOLID principles states that:

Every class should have a single responsibility (a reason to change - JK), and that responsibility should be entirely encapsulated by the class

In other words, class should do one thing and one thing only. OrderDocumentFactory, what does it do? It builds XML. If our requirements evolved so that we need to return slightly different XML, that is our one reason to change class in question. Building XML is our single responsibility.

Unfortunately, OrderDocumentFactory also has second, hidden responsibility – it calculates discount. Had we decided bonus discount is no longer supported, we’ll have to modify OrderDocumentFactory class. This is strange because why would document factory had anything to do with discount calculation? If we wanted to change discount calculation logic we should be rather looking to modify DiscountCalculator class. And there goes our problem – we have one class pretending to be two2.

SOLID solution

We already know what to do. We need a second class that will handle discount calculation logic. All right then, is this code unit testable now?

public XDocument CreateDocument(Order order)
{
    var document = new XDocument();
    var discount = new DiscountCalculator().CalculateDiscount(order);
    document.Add(new XElement("Order",
        new XElement("Date", order.Date.ToShortDateString()),
        new XElement("OriginalValue", order.TotalValue),
        new XElement("Discount", discount)
    ));

    return document;
}

Not so fast. This “solution” adds another responsibility to CreateDocument method – instance creation. We do not want that. What if DiscountCalculator required some constructor arguments? Where would CreateDocument take them from? Instance creation is almost always out of scope of any class responsibilities. We need dependency injection:

public class OrderDocumentFactory
{
    public OrderDocumentFactory(IDiscountCalculator discountCalculator)
    {
        this.discountCalculator = discountCalculator;
    }

    public XDocument CreateDocument(Order order)
    {
        var document = new XDocument();
        var discount = discountCalculator.CalculateDiscount(order);
        document.Add(new XElement("Order",
            new XElement("Date", order.Date.ToShortDateString()),
            new XElement("OriginalValue", order.TotalValue),
            new XElement("Discount", discount)
        ));

      return document;
    }

    private readonly IDiscountCalculator discountCalculator;
}

With code structured like this you don’t have to mock private method but instead you mock dependency, IDiscountCalculator, which is the usual course of action.

Conclusion

In most of the cases the need to mock private method originates from poor design. Design that is already causing problems (inability to write unit tests) and will cause more problems as the code grows. Solution is simple:

  • Fix your design by sticking to SOLID principles
  • Class should do one thing and one thing only; the fact that you need to mock private method of your class usually indicates there is a second class with different responsibility hiding there
  • Any additional responsibilities should be extracted as separate components and provided to class in question via dependency injection

Unit tests are much like your good buddy. When dealing with your code they will be first to ask “Wait a second, this cannot be right?”. Mocking private method cannot be right. And it is not.

  1. We have to make important assumption here - you can change problematic code.

  2. Private CreateDiscount method is a class in disguise.

Comparing lists with NUnit – the definite guide

January 02, 2015 | tags: c# unit-testing nunit list

Very often you’ll run into situation where in your unit test you have to compare two lists against each other. In this post I show several ways to do that, describe common pitfalls and nuances.

Simple types with Assert.AreEqual

When our list contains “simple type”1 like int or string assertion is rather straightforward. There is plethora of different methods we could use but for now NUnit’s Assert.AreEqual should be enough:

[Test]
public void SimpeTypes_Integer()
{
    var expected = new List<int> { 1, 2, 5 };
    var actual = new List<int> { 1, 2, 5 };

    CollectionAssert.AreEqual(expected, actual); // collections specific
    Assert.AreEqual(expected, actual);           // classic model
    Assert.That(actual, Is.EqualTo(expected));   // constraint model
}

NUnit will then use its custom EnumerablesEqual to verify whether each element of actual has its corresponding element in expected (note that both lists have to be in the same order). Comparison of individual elements will default to Equals call.

In case order of elements is irrelevant we’ll have to use Equivalent comparison instead:

[Test]
public void SimpleTypes_IntNotInOrder()
{
    var expected = new List<int> { 1, 2, 5 };
    var actual = new List<int> { 1, 5, 2 };

    CollectionAssert.AreEquivalent(expected, actual);
    Assert.That(actual, Is.EquivalentTo(expected));
}

Custom types

Problems arise when we have to compare collections that contain our custom-defined types. Consider this naive Quotation type which stores information about stock closing price:

public class Quotation
{
    public string Ticker { get; set; }
    public DateTime Date { get; set; }
    public decimal Close { get; set; }
}

The following test will naturally fail as we know even though compared quotations are semantically the same, they are in fact, different instances:

[Test]
public void CustomTypes_Quotation()
{
    var expected = CreateQuotations().ToList();
    var actual = CreateQuotations().ToList();

    Assert.AreEqual(expected, actual);
    Assert.That(expected, Is.EqualTo(actual));
}

private IEnumerable<Quotation> CreateQuotations()
{
    var date = new DateTime(2014, 07, 31);
    yield return new Quotation { Ticker = "APPL", Close = 110.38m, Date = date };
    yield return new Quotation { Ticker = "MSFT", Close =  46.45m, Date = date };
}

This is easily fixable though. Remember how I mentioned NUnit will default to using Equals in individual objects comparisons? All we have to do is provide one. Or do we? There are few issues with such approach:

  • To do it correctly, we’ll have to implement not only Equals but also GetHashCode (which has nothing to do with our original problem).
  • It forces us to extend our custom class with test-only implementation. While it is true that unit tests will often drive design of our code, the changes should come from how our code is used, not from testing frameworks limitations.

Since there doesn’t seem to be any better way to do this2, for now we’ll implement Equals to make the test pass.

Problem with reference types

What about types we cannot override Equals? Like XElement? We could project our collection to bit more representable form:

[Test]
public void ReferenceTypes_XElement()
{
    var list = new List<XElement> { new XElement("a"), new XElement("b") };
    var expected = list.Select(x => x.ToString()).ToList();
    var actual = list.Select(x => x.ToString()).ToList();

    CollectionAssert.AreEqual(expected, actual);
    Assert.AreEqual(expected, actual);
    Assert.That(expected, Is.EqualTo(actual));
}

This works but you can probably already see problems with such approaches – we have to add methods we don’t really need (Equals), use methods that were not meant to be used this way (ToString) or resort to overly complex solutions. It looks very clumsy. We need to find a better way.

Enter FluentAssertions

Just like virtually any problem you might ever encounter this one has, too, already been solved. FluentAssertions is a library that contains a set of extensions to make asserts more fluent (name kind of spoiled it). On top of really good API and clear error messages it provides solutions for common assertions problems, like the one we are facing here.

The ShouldBeEquivalentTo extension method is what we are looking for. It is a smart method that will compare entire objects graph and apply appropriate strategy depending on underlying types. In our case, the actual XMLs will be compared (or to be more specific, properties of XElement that are relevant to XML semantics). This makes our test look like this:

[Test]
public void ReferenceTypes_XElement()
{
    var expected = new List<XElement> { new XElement("a"), new XElement("b") };
    var actual = new List<XElement> { new XElement("b"), new XElement("a") };

    actual.ShouldBeEquivalentTo(expected);
}

You might have noticed I changed the order of elements in actual and expected lists. By default ShouldBeEquivalentTo performs orderless comparison (same as NUnit’s Is.EquivalentTo). Changing this behavior is as easy as this:

[Test]
public void ReferenceTypes_XElementOrderMatters()
{
    var expected = new List<XElement> { new XElement("a"), new XElement("b") };
    var actual = new List<XElement> { new XElement("a"), new XElement("b") };

    actual.ShouldBeEquivalentTo(
        expected,
        options => options.WithStrictOrdering()
    );
}

In case order is different we’ll get helpful message explaining what’s going on:

Expected item[0].Name.LocalName to be “a”, but “b” differs near “b” (index 0).
Expected item[1].Name.LocalName to be “b”, but “a” differs near “a” (index 0).

We can also get rid of Equals method on our Quotation class. ShouldBeEquivalentTo will compare type’s public properties against each other to a decent depth level – they don’t even have to be the same type (all of this is highly configurable).

ShouldBeEquivalentTo is just one of multitude of methods and approaches you can use. For collections alone there’s 20+ custom methods. Resulting assertions are fluent. I bet you know exactly what’s going on in the following snippet without a word of explanation:

actual
  .Should()
  .HaveCount(2).And
  .OnlyContain(q => q.Date == 31.July(2014)).And
  .ContainSingle(q => q.Ticker == "MSFT");

Notice the 31.July(2014). It is FluentAssertions’s fluent API for date & time.

Conclusion

I barely scratched the surface of FluentAssertions. It supports many different types, has excellent extensibility options, is highly configurable, produces meaningful error messages and very readable unit tests code. Go discover it all yourself. Forget about NUnit’s Assert. Even though it is good API, FluentAssertions is simply vastly superior. Once you’ll start using it you will never go back.

The definite guide contains single rule – start using FluentAssertions.

  1. By “simple type” I mean catch-all phrase for CLR primitive or any other value type or System.String; not simple type as understood by C# spec

  2. We could implement a workaround using Has.All.Matches but this is not the direction we want to go

Unit testing streams with FakeItEasy

December 21, 2014 | tags: c# unit-testing fakeiteasy tdd

Imagine you need to add a simple, new feature to your application - a class which logs changes made to entities and saves them in XML file. For example, when user edits his profile to change his first name, we expect this XML to be produced:

<Changes type="User">
  <FirstName>Bobby</FirstName>
</Changes>

Simple? Let’s write a test.

Enter TDD

Directly translating our requirement from above to unit test code will look more or less like this:

[Test]
public void LogChanges_SavesChangedFirstNameToXml()
{
    const string ExpectedXml = 
      "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + 
      "<Changes type=\"User\"><FirstName>Bobby</FirstName></Changes>";
    var userChangeLogger = new UserChangeLogger();
    var oldUser = new User { FirstName = "John" };
    var newUser = new User { FirstName = "Bobby" };
    
    userChangeLogger.LogChanges(oldUser, newUser);
    
    // now what?
}

Exactly, now what? Assuming how tested class is supposed to work, we need to read some file in order to verify the XML. Wait one second… “read some file” in unit test? This is not how you produce high quality, maintainable code and fast running unit tests. It seems that implementation we thought about is not testable (as for now).

Naive implementation

Our problem exists because of .NET framework API being excellent. I/O tasks usually take 2 lines of code once you find appropriate method(s). Generating XML is no different thanks to LINQ to XML:

public void LogChanges(User originalUser, User changedUser)
{
    if (originalUser.FirstName != changedUser.FirstName)
    {
        var userChangesXml = new XElement("Changes",
            new XElement("FirstName", changedUser.FirstName));
        userChangesXml.Save(@"UserChanges.xml");
    }
}

The Save method is our main offender. Under the hood it creates file in local directory and writes XElement content to it. This is a no-go if we want to have it unit tested.

Utilizing System.IO.Stream

While this might be cool feature it does not really get us anywhere in terms of testability. Not to mention, we might need a little bit more control over when and how files are created. The flexibility we are looking for is all there in Stream class:

using (var fileStream = File.Open(@"UserChanges.xml", FileMode.Create))
{
    var userChangesXml = new XElement("Changes",
        new XElement("FirstName", changedUser.FirstName));
    userChangesXml.Save(fileStream);
}

Almost there. We need to remove that hard dependency to File otherwise we won’t be able to mock it in test with tools we got (FakeItEasy). This is usually done by wrapping I/O methods with class implementing custom interface and injecting such wrapper as a dependency. Final, fully-testable version of our class looks like this:

class UserChangeLogger
{
    public UserChangeLogger(IFileStreamFactory fileStreamFactory)
    {
        this.fileStreamFactory = fileStreamFactory;
    }

    public void LogChanges(User originalUser, User changedUser)
    {
        if (originalUser.FirstName != changedUser.FirstName)
        {
            using (var stream = fileStreamFactory
                .CreateFileStream(@"UserChanges.xml"))
            using (var writer = XmlWriter.Create(stream))
            {
                var userChangesXml = new XElement("Changes",
                    new XElement("FirstName", changedUser.FirstName));
                userChangesXml.WriteTo(writer);
            }
        }
    }

    private IFileStreamFactory fileStreamFactory;
}

Good! Let’s get back to our test that we had problem writing in first place and change it accordingly:

[Test]
public void LogChanges_SavesChangedFirstNameToXml()
{
    const string ExpectedXml = 
      "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + 
      "<Changes type=\"User\"><FirstName>Bobby</FirstName></Changes>";
    // we set up our new dependency and "tell" it to return stream
    // so that later we can check what have been written to it
    var fileStreamFactory = A.Fake<IFileStreamFactory>();
    var memoryStream = new MemoryStream();
    A.CallTo(() => fileStreamFactory.CreateFileStream(@"UserChanges.xml"))
        .Returns(memoryStream);
    var userChangeLogger = new UserChangeLogger(fileStreamFactory);
    var originalUser = new User { FirstName = "John" };
    var changedUser = new User { FirstName = "Bobby" };

    userChangeLogger.LogChanges(originalUser, changedUser);

    memoryStream.Position = 0;
    var savedXml = new StreamReader(memoryStream).ReadToEnd();
    Assert.That(savedXml, Is.EqualTo(ExpectedXml);
}

Alright! The code is now 100% testable and we seem to be done. Or do we?

Unfortunately, this test fails with an error saying that we “Cannot access a closed Stream”. Upon closer inspection, the stream returned by IFileStreamFactory fake is used within using statement which disposes IDisposable (which in case of Stream closes it and renders unusable past using block). In order to save stream content for later inspection in unit test we have to somehow record it while it is being written. The only time-window we can access our stream is within using block.

Remember that IFileStreamFactory we introduced to make our class testable in first place? It returns Stream which is an abstract class. That means we could simply create a derived class, say RecordingStream, which would store whatever is written to stream for future retrieval.

Enter FakeItEasy

Implementing 10-or-so Stream members seems rather excessive when all we need is to hook into Write method. Fortunately, we can use FakeItEasy to cover both the necessary and unnecessary stuff.

1. Fake Stream instance

First, we need usable Stream. This is fairly simple:

var fakeStream = A.Fake<Stream>();
A.CallTo(() => fakeStream.CanWrite).Returns(true);
A.CallTo(() => fakeStream.CanRead).Returns(true);

2. Saving Stream content

Next, in order to get stream to store its content we need to configure Write and WriteByte methods (and their async versions if you are on .NET 4.5+). This can be done using FakeItEasy’s Invokes method which allows us to execute custom code when call to faked method is made:

// The _ is FakeItEasy's shortcut to match-any
A.CallTo(() => fakeStream.Write(A<byte[]>._, A<int>._, A<int>._))
    .Invokes(call =>
    {
        // call variable stores original method invocation details
        // including arguments which is all we need here
        var offset = call.GetArgument<int>(1);
        var count = call.GetArgument<int>(2);
        var content = call.GetArgument<byte[]>(0)
            .Skip(offset)
            .Take(count)
            .ToArray();
        // save content
        bytesWritten.AddRange(content);
    });
// Similar for WriteByte method

3. Extracting saved content

Having raw bytes in unit test is far from optimal as we will be rather making string-to-string asserts. We need to access those bytes in more friendly format, like string. To do this we will use Encoding.GetString()1 method:

return new UTF8Encoding().GetString(bytesWritten.ToArray());

We wrap it all up and put inside a custom class, StreamRecorder (follow the link to view its final form on my GitHub repository). With few modifications to unit test code we are now officially done.2

Conclusion

Today, we have discovered two major obstacles when it comes to unit testing:

  1. Interaction with external resources (file, network, driver - you name it) is difficult to implement with testability in mind.
  2. .NET framework API does not always support writing unit tests.

By overcoming them we have laid down important foundation. From now on, anyone implementing any sort of file writing will have components needed to do it in testable manner (IFileStreamFactory) and easily test it (StreamRecorder) while keeping code up to the highest standards.

Sample code for this article can be found at my GitHub repository.

  1. We use UTF8 because that is the default for .NET. This can naturally be configured in case we need to write in different encoding.

  2. There is still room for improvement though. Like I mentioned, 1) encoding could be configurable, 2) XMLs could be loaded from embedded resources rather than hand-typed in code, 3) asserts could be made for XElements rather than strings with FluentAssertions