Declarative mocking

Mocking complements the test-driven development (TDD) allowing developers to write small and concise unit tests for components with external dependencies that would otherwise be hard or impossible to test. As the software becomes more and more distributed and loosely coupled, mocking becomes an intrinsic part of TDD process. While there are good tools and established best practices for mocking in .NET, most of the currently widely used approaches are imperative. Imperative code tends to be verbose, less expressive and describes how a mocking behavior is achieved rather what behavior is desired. On the other hand, nowadays new technologies make it possible to build declarative mocking tools and frameworks.

Let’s start with a few examples (I try to avoid artificially examples, e.g. ICalculator-like, because they don’t explain the properties of real projects). Suppose you work on a mobile social app that consumes external weather service. The app sends the current coordinates (latitude and longitude) and gets back JSON data as a string. You define the service interface as:

public interface IWeatherService
{
    string GetCurrent(float latitude, float longitude);
}

The service implementation does a REST call to get the data. For my current location, the REST call looks like the following:

http://api.openweathermap.org/data/2.5/weather?lat=42.7&lon=23.3

Once the app gets the data it should suggest places where the user can meet with friends. Depending on the current weather, the app should suggest an indoor or outdoor place. A possible implementation of this feature may look like the following:

public enum Sky
{
    Cloudy,
    PartiallyCloudy,
    Clear
}

public enum PlaceType
{
    Indoor,
    Outdoor
}

public class WeatherModel : Model
{
    private readonly IWeatherService weatherService;

    public WeatherModel(IWeatherService weatherService)
    {
        if (weatherService == null)
        {
            throw new ArgumentNullException("weatherService");
        }
        this.weatherService = weatherService;
    }

    public PlaceType SuggestPlaceType(float latitude, float longitude)
    {
        var sky = this.GetCurrentSky(latitude, longitude);

        return sky.Equals(Sky.Clear)
                ? PlaceType.Outdoor
                : PlaceType.Indoor;
    }

    private Sky GetCurrentSky(float latitude, float longitude)
    {
        var data = this.weatherService.GetCurrent(latitude, longitude);

        dynamic json = JsonConvert.DeserializeObject(data);

        var value = json.weather[0].main.Value as string;

        var sky = (Sky)Enum.Parse(typeof(Sky), value);

        return sky;
    }

    // the rest is omitted for brevity
}

The implementation is quite straightforward. It provides a simple design for dependency injection via WeatherModel constructor and SuggestPlaceType method keeps the logic simple by delegating most of the work to a private method.

As we said before, the implementation of IWeatherService does a REST call. This requires that the test server(s) should have internet connection available. This is a serious restriction because most test environments are not internet-connected.

To solve this issue we can use any modern mocking framework (e.g. Moq, JustMock, NSubstitute, FakeItEasy and so on). In this case I am going to use JustMock.

[TestMethod]
public void TestSuggestedPlaceType()
{
    // Arrange
    var weatherSvc = Mock.Create<IWeatherService>();

    var latitude = 42.7f;
    var longitude = 23.3f;
    var expected = "{'coord':{'lon':23.3,'lat':42.7},'sys':{'country':'BG','sunrise':1380428547,'sunset':1380471081},'weather':[{'id':800,'main':'Clear','description':'Sky is Clear','icon':'01d'}],'base':'gdps stations','main':{'temp':291.15,'pressure':1015,'humidity':72,'temp_min':291.15,'temp_max':291.15},'wind':{'speed':1,'deg':0},'rain':{'3h':0},'clouds':{'all':0},'dt':1380439800,'id':6458974,'name':'Stolichna Obshtina','cod':200}";
    Mock.Arrange(() => weatherSvc.GetCurrent(latitude, longitude)).Returns(expected);

    // Act
    var model = new WeatherModel(weatherSvc);
    var suggestedPlaceType = model.SuggestPlaceType(latitude, longitude);

    // Assert
    Assert.AreEqual(PlaceType.Outdoor, suggestedPlaceType);
}

I prefer Arrange-Act-Assert (AAA) pattern for writing unit tests because it makes it simple and easy to read. As we can see, in this scenario the unit test is quite concise: 2 lines for the arrangement, 2 lines for the action,1 line for the assertion and a few lines for local variable definitions and comments. In fact, any modern mocking library can do it in a few lines. It doesn’t matter if I use JustMock or Moq or something else.

The point is, in such simple scenarios any mocking framework usage will result in simple and nice to read unit tests. Before we continue, I would like to remind you that both JustMock and Moq are imperative mocking frameworks. So are NSubstitute and FakeItEasy and many others. This means that we have explicitly to command the mocking framework how the desired behavior is achieved.

So far, we saw that imperative mocking frameworks do very well in simple scenarios. Let’s see an example where they don’t do well and see how declarative mocking can help. Suppose you work on invoice module for a CRM system. There is a requirement that the invoice module should send an email when there are more than 3 delayed invoices for a customer. A possible implementation may look as it follows:

public interface ISpecializedList<T>
{
    void Add(T item);

    void Reset();

    uint Count { get; }

    // the rest is omitted for brevity
}

public interface ICustomerHistory
{
    ISpecializedList<Invoice> DelayedInvoices { get; }

    // the rest is omitted for brevity
}

public class InvoiceManager
{
    private readonly ICustomerHistory customerHistory;

    public static readonly uint DelayedInvoiceCountThreshold = 3;

    public InvoiceManager(ICustomerHistory customerHistory)
    {
        if (customerHistory == null)
        {
            throw new ArgumentNullException("customerHistory");
        }
        this.customerHistory = customerHistory;
    }

    public void MarkInvoiceAsDelayed(Invoice invoice)
    {
        var delayedInvoices = this.customerHistory.DelayedInvoices;

        delayedInvoices.Add(invoice);

        if (delayedInvoices.Count > DelayedInvoiceCountThreshold)
        {
            this.SendReport(invoice.Customer);
        }
    }

    private void SendReport(Customer customer)
    {
        // send report via email

        this.ReportSent = true;
    }

    public bool ReportSent
    {
        get; private set;
    }

    // the rest is omitted for brevity
}

Let’s write the unit test. I am going to use JustMock.

[TestMethod]
public void TestSendReportWhenDelayOrderThresholdIsExceeded()
{
    // Arrange
    var history = Mock.Create<ICustomerHistory>();

    uint count = 0;

    Mock.Arrange(() => history.DelayedInvoices.Add(Arg.IsAny<Invoice>())).DoInstead(new Action(() =>
    {
        Mock.Arrange(() => history.DelayedInvoices.Count).Returns(++count);
    }));

    // Act
    var invoiceMananger = new InvoiceManager(history);
    invoiceMananger.MarkInvoiceAsDelayed(new Invoice());
    invoiceMananger.MarkInvoiceAsDelayed(new Invoice());
    invoiceMananger.MarkInvoiceAsDelayed(new Invoice());
    invoiceMananger.MarkInvoiceAsDelayed(new Invoice());

    // Assert
    Assert.IsTrue(invoiceMananger.ReportSent);
}

This time the unit test looks quite complicated. We have to use DoInstead method to simulate the internal workings of ISpecializedList<T> implementation. Said in another words we have code duplication. First, there is a code that increments the Count property of ISpecializedList<T> implementation we use in production. Second, there is a code that increment the Count property in our test for the sole purpose of the test. Also, note that now we have count local variable in our test.

Let’s compare the two scenarios and see why the last test is so complicated. In the first scenario we don’t have a mutable object state while in the second one we have to take care for the Count property. This is an important difference. Usually a good program design says that a method with a return value doesn’t change the object state, while a method without a return value does change the object state. After all, it is common sense.

Suppose we have to write a unit test for the following method:

public void CreateUser(string username, string password) { ... }

This method doesn’t return a value. However, it changes the system state. Usually, when we write a unit test for void method we assert that the system is changed. For example, we can assert that we can login with the provided username and password.

Another option is to change the method signature so the method returns a value:

public bool /* success */ CreateUser(string username, string password) { ... }
// or
public int /* user id */ CreateUser(string username, string password) { ... }

However this is not always possible or meaningful.

So, we see that mocking even a simple interface like ISpecializedList<T> complicates the unit tests. This is a consequence of imperative mocking approach. Let’s see a hypothetical solution based on FakeItEasy syntax.

[TestMethod]
public void TestAddItem()
{
    // Arrange
    var list = A.Fake<ISpecializedList<Invoice>>();

    A.CallTo(() => list.Add(A<Invoice>.Ignored).Ensures(() => list.Count == list.Count + 1);

    // Act
    list.Add(new Invoice());
    list.Add(new Invoice());
    list.Add(new Invoice());

    // Assert 
    Assert.AreEqual(3, list.Count);
}

In this case we removed the need of count local variable and made the test shorter and a more expressive. The Ensures method accepts a lambda expression that describes the next object state. For example, we can arrange Reset method as follows:

A.CallTo(() => list.Reset()).Ensures(() => list.Count == 0);

Let’s see two more examples. We can arrange a mock for IDbConnection as follows:

IDbConnection cnn = ...;

A.CallTo(() => cnn.CreateCommand()).Returns(new SqlCommand());
A.CallTo(() => cnn.Open()).Ensures(() => cnn.State == ConnectionState.Open);
A.CallTo(() => cnn.Close()).Ensures(() => cnn.State == ConnectionState.Closed
						&& A.FailureWhen<InvalidOperationException>(() => cnn.BeginTransaction()));
A.CallTo(() => cnn.Database).FailsWith<NotImplementedException>();
A.CallTo(() => cnn.BeginTransaction()).FailsWhen<InvalidOperationException>(() => cnn.State != ConnectionState.Open);

This code fragment shows how we can describe the state machine behind IDbConnection instance. Similarly, we can arrange a mock for TextReader as follows:

TextReader reader = ...;

A.CallTo(() => reader.Read()).Requires(() => reader.CanRead);
A.CallTo(() => reader.Read()).Returns(0);
A.CallTo(() => reader.Close()).Ensures(() => A.FailureWhen<InvalidOperationException>(() => reader.Read()));
A.FailureWhen<Exception>(() => reader.ReadBlockAsync(null, 0, 0));

While a fluent API can help with declarative mocking it surely has limits. Both Requires and Ensures methods describe invariants but the lambda expressions become harder to read when they grow in size. So I started looking for improvements.

First, I decided to try Roslyn. It turns out that Roslyn is quite good framework for my purposes. My current approach is to define mock types as regular classes (I find some limitations of this approach and more research is needed). Instead of using fluent API I can define a mock type in the source code.

public mock class MockList<T> : ISpecializedList<T>
{
    public void Add(T item)
        ensures Count == Count + 1;

    public void Reset()
        ensures Count == 0;

    public uint Count
    {
        get;
    }
}

I borrowed ensures clause from Spec# and added mock modifier to the class definition. Then I used Roslyn API to hook and emit a simple throw new NotImplementedException(); for every method.
screenshot

I also emitted DescriptionAttribute for every ensures clause. I guess, it will be better to emit a reference to a custom attribute defined in another assembly but for now I decided to keep it simple. Now we can rewrite the previous TestAddItem test as follows:

[TestMethod]
public void TestAddItem()
{
    // Arrange
    var list = new MockList<Invoice>();

    // Act
    list.Add(new Invoice());
    list.Add(new Invoice());
    list.Add(new Invoice());

    // Assert 
    Assert.AreEqual(3, list.Count);
}

With the current implementation this test will fail with NotImplementedException but the test itself is short and easy to read. For further development I see two options. The first one is to make Roslyn to emit the correct ILASM corresponding to the expressions defined via requires and ensures clauses. The second option is to emit an interface rather a class and to keep requires and ensures clauses encoded as attributes. Then, at runtime the mocking API can create types that enforce the defined invariants. I think the second option is more flexible than the first one.

Besides Roslyn, there is another approach that can make mocking easier. Recently I came upon the concept of prorogued programming. Using this technique the developer can train the mocks used in the unit tests so that the desired behavior is achieved during the test runs. While this approach may seem semi-automated I find it very attractive. I think it has a lot of advantages and if there is a good tooling support it may turn out this is a better way to go.

What’s next? I will research the Roslyn approach further. There are two options:

  • (static) using Roslyn API to emit ILASM at compile time
  • (dynamic) using Roslyn to emit interfaces and metadata and then using mocking API at runtime to provide the actual implementation

Both options have tradeoffs and a careful analysis is needed. Prorogued programming seems very suitable technique to make mocking easier so I need to investigate it further. Stay tuned.

Further reading:

 

Mobile Application Development

Mobile application development is more popular than ever. Today, there are tens of mobile application development platforms (MADPs) that fight for adoption and market share. In this post, I am going to share what characteristics a good, in my opinion, MADP should have.

Let’s start with some facts and obvious trends. Today, most of us have a mobile device of some sort and the trend is that mobile devices would become even more popular. So, it is a growing market with a lot of opportunities. To stay competitive on the market, you must have shorter product release cycles while maintaining excellent product quality. Using a MADP is one way to achieve the aforementioned goals.

So, you have this wonderful idea for a mobile application and you want it to be a big success. First, you have to build it. Let’s dig in the build process. Many applications start their live as a series of visual concepts. Usually the app author has mind models for some user interfaces (UIs), e.g. some buttons, labels, text boxes, etc. and some logic behind these UIs. A good MADP should reflect this thought process and should provide model-view-controller (MVC) paradigm for app development. Good news is that today’s modern MADPs support MVC design pattern. It should be mentioned that a MADP should support both declarative and imperative¬†ways to define a UI. Another important aspect of the declarative UI programming is that the declarative language should be both easy and powerful. Nobody demands that all MADPs should use the same UI declarative language but it should be easy for us mere developers to switch between different MADPs when it does make sense.

We touched an important part of the application development – the programming language. A good MADP should use as common as possible programming language (in an ideal world MADP should support multiple programming languages). There is no point to have superb MADPs that use uncanny or esoteric languages. The entering barrier should be as low as possible. Using well-know and popular languages has a lot of benefits. Your developers can be easily trained in case they are not experienced with it. Another advantage is that there will be a lot of frameworks, components and libraries for that language. The presence of package manager like NuGet, npm or gem is also a big advantage. Community driven package repositories are invaluable and a big time saver. Of course, sometimes a MADP may offer new possibilities at the cost of a new or unpopular programming language and in this case I would recommend to carefully reconsider all the risks.

A closely related topic to the programming language is the IDE. For some developers it is a bit controversial topic but there are many others that find using an IDE a good practice. In general, a good MADP should not tie you up to a particular IDE and should allow building applications without an IDE as well. But for many developers the presence of an IDE is reassuring. Providing features as auto-completion, visual debugging, navigation and code refactoring may increase developer productivity. An IDE can also provide visual designers to support MVC design pattern as well.

While we examined the programming language and its surrounding ecosystem, our main focus was on the usage of local frameworks, components and libraries. We haven’t look at cloud services though. A good MADP should offer the following minimal set of cloud services: data services for storing application data, authentication services for managing user and application identities, push notification services for notifying mobile application about important events, integration data services for integrating and sharing data with other applications and custom application services for building common application logic blocks.

So far, we talked a lot about source code. Ultimately, this source code must be stored somewhere. In some cases, before you start with the project you already have the source code for some of components in your repository. A good MADP should support external source code repositories and support the most common source control systems (e.g. git, svn, mercurial, etc). This is an important requirement as we will read about testing and deploying in the next paragraphs.

We covered the major part of the building mobile application. This is only a part from build-test-deploy cycle though. While most developers are aware of the benefits of continuous integration (CI) solutions and embrace test-drive development (TDD) practices, they often underestimate the last part of build-test-deploy cycle. I am going to explore the last two parts together as the test part should test the deployment as well. Often, there is a friction in deployment process that forces the developers to test their app on a few platforms only. The problem is that the variety of mobile devices is enormous and there are good chances that your app won’t work correctly on some devices. Instead of testing and deploying your app on five or ten devices you should better test it on dozens of devices. A good MADP will automate as much as possible starting with CI, automated unit testing, deployment and automated UI/integration testing. A MADP should provide intelligent test scenarios for different mobile platforms and operating systems.

Okay, we have built and released our application, now what? Now comes another important thing – collecting and analyzing user feedback. My experience shows it is rarely that an app becomes success since its first release. Usually this is not the case. You release the first version and then start gathering user feedback what they like and dislike, what they want to see in next app versions and so on. Analyzing the user feedback is a hard task. There will be always users that likes your app and other that dislike it. It is a tricky thing what you should implement, change or improve in the next app version. To be able to take the right decision you should be correctly informed. This means that you should be able to collect and measure the user feedback. Once you have the data you can analyze it and take the proper actions. In my opinion, the hardest part is to engage the users to send you a feedback about their experience. A MADP should provide means that allow you to collect user experience data with minimal intrusion. Survey dialogs and rating forms just don’t work. A MADP should provide instruments to infer user experience from the application usage. There is a technical aspect as well. Collecting crash reports, call stacks and performance data from your app in also very important. Nobody likes unstable or slow apps. A MADP should provide mechanisms for collecting crash, bug and performance reports without any trouble for the end user.

In conclusion, a good MADP should:

  • support MVC design pattern
  • provide both declarative and imperative UI programming
  • use popular and well-know programming language
  • provide package manager
  • provide an optional IDE
  • provide rich cloud services
  • support as many as possible external source control systems
  • automate as much as possible and remove the friction in build-test-deploy cycle
  • collect and analyze user feedback and technical reports

Some of the existing MADPs claim they already provide these capabilities. Check it out yourself.