Tag Archives: Dependency Injection

Using NSubstitute for partial mocks

I have previously written about how to, effectively, subclass using Nsubstitute; in this post, I’ll cover how to partially mock out that class.

Before I get into the solution; what follows is a workaround to allow badly written, or legacy code to be tested without refactoring. If you’re reading this and thinking you need this solution then my suggestion would be to refactor and use some form of dependency injection. However, for various reasons, that’s not always possible (hence this post).

Here’s our class to test:

public class MyFunkyClass
{
    public virtual void MethodOne()
    {        
        throw new Exception("I do some direct DB access");
    }
 
    public virtual int MethodTwo()
    {
        throw new Exception("I do some direct DB access and return a number");

        return new Random().Next(5);
    }
 
    public virtual int MethodThree()
    {
        MethodOne();
        if (MethodTwo() <= 3)
        {
            return 1;
        }
 
        return 2;
    }
}

The problem

Okay, so let’s write our first test:

[Fact]
public void Test1()
{
    // Arrange
    MyFunkyClass myFunkyClass = new MyFunkyClass();
 
    // Act
    int result = myFunkyClass.MethodThree();
 
    // Assert
    Assert.Equal(2, result);
}

So, what’s wrong with that?

Well, we have some (simulated) DB access, so the code will error.

Not the but a solution

The first thing to do here is to mock out MethodOne(), as it has (pseudo) DB access:

[Fact]
public void Test1()
{
    // Arrange
    MyFunkyClass myFunkyClass = Substitute.ForPartsOf<MyFunkyClass>();
    myFunkyClass.When(a => a.MethodOne()).DoNotCallBase();
 
    // Act
    int result = myFunkyClass.MethodThree();
 
    // Assert
    Assert.Equal(2, result);
}

Running this test now will fail with:

Message: System.Exception : I do some direct DB access and return a number

We’re past the first hurdle. We can presumably do the same thing for MethodTwo:

[Fact]
public void Test1()
{
    // Arrange
    MyFunkyClass myFunkyClass = Substitute.ForPartsOf<MyFunkyClass>();
    myFunkyClass.When(a => a.MethodOne()).DoNotCallBase();
    myFunkyClass.When(a => a.MethodTwo()).DoNotCallBase();
 
    // Act
    int result = myFunkyClass.MethodThree();
 
    // Assert
    Assert.Equal(2, result);
}

Now when we run the code, the test still fails, but it no longer accesses the DB:

Message: Assert.Equal() Failure
Expected: 2
Actual: 1

The problem here is that, even though we don’t want MethodTwo to execute, we do want it to return a predefined result. Once we’ve told it not to call the base method, you can then tell it to return whatever we choose (there are separate events – see the bottom of this post for a more detailed explanation of why); for example:

[Fact]
public void Test1()
{
    // Arrange
    MyFunkyClass myFunkyClass = Substitute.ForPartsOf<MyFunkyClass>();
    myFunkyClass.When(a => a.MethodOne()).DoNotCallBase();
    myFunkyClass.When(a => a.MethodTwo()).DoNotCallBase();
    myFunkyClass.MethodTwo().Returns(5);
 
    // Act
    int result = myFunkyClass.MethodThree();
 
    // Assert
    Assert.Equal(2, result);
}

And now the test passes.

TLDR – What is this actually doing?

To understand this better; we could do this entire process manually. Only when you’ve felt the pain of a manual mock, can you really see what mocking frameworks such as NSubtitute are doing for us.

Let’s assume that we don’t have a mocking framework at all, but that we still want to test MethodThree() above. One approach that we could take is to subclass MyFunkyClass, and then test that subclass:

Here’s what that might look like:

class MyFunkyClassTest : MyFunkyClass
{
    public override void MethodOne()
    {
        //base.MethodOne();
    }
 
    public override int MethodTwo()
    {
        //return base.MethodTwo();
        return 5;
    }
}

As you can see, now that we’ve subclassed MyFunkyClass, we can override the behaviour of the relevant virtual methods.

In the case of MethodOne, we’ve effectively issued a DoNotCallBase(), (by not calling base!).

For MethodTwo, we’ve issued a DoNotCallBase, and then a Returns statement.

Let’s add a new test to use this new, manual method:

[Fact]
public void Test2()
{
    // Arrange 
    MyFunkyClassTest myFunkyClassTest = new MyFunkyClassTest();
 
    // Act
    int result = myFunkyClassTest.MethodThree();
 
    // Assert
    Assert.Equal(2, result);
}

That’s much cleaner – why not always use manual mocks?

It is much cleaner if you always want MethodThree to return 5. Once you need it to return 2 then you have two choices, either you create a new mock class, or you start putting logic into your mock. The latter, if done wrongly can end up with code that is unreadable and difficult to maintain; and if done correctly will end up in a mini version of NSubstitute.

Finally, however well you write the mocks, as soon as you have more than one for a single class then every change to the class (for example, changing a method’s parameters or return type) results in a change to more than one test class.

It’s also worth mentioning again that this problem is one that has already been solved, cleanly, by dependency injection.

Using Entity Framework with IoC

One thing to bear in mind about using entity framework is that the DbContext object is not thread safe. This threw me when I first discovered it; it also confused why I was getting this error, as I was running in an environment that I thought was pretty much single threaded (in fact, it was an Azure function). I was using IoC and so the DbContext is shared across instances.

Because the error is based on, effectively, a race condition, your mileage may vary, but you’ll typically get one of the following errors:

System.InvalidOperationException: ‘The context cannot be used while the model is being created. This exception may be thrown if the context is used inside the OnModelCreating method or if the same context instance is accessed by multiple threads concurrently. Note that instance members of DbContext and related classes are not guaranteed to be thread safe.’

System.InvalidOperationException: ‘A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.’

I had a good idea what the cause of this might be, but in order to investigate, I set-up a console app accessing Entity Framework; in this case, EF Core.

If you’re here to find a solution, then you can probably scroll down to the section labelled To Fix.

Reproducing the error

To reproduce the error, we need to introduce Unity (I imagine the same would be true of any IoC provider, as the problem is more with the concept than the implementation):

Install-Package Unity

The next step is to abstract away the data access layer, in order to provide a base for our dependency injection:

As you can see, we’re introducing a data access layer – and we’re creating an interface for our DbContext. The idea being that this can subsequently be resolved by Unity. Here are our interfaces:

public interface IDataAccess
{
    List<string> GetData();
 
    void AddData(List<string> newData);
}

public interface IMyDbContext
{
    DbSet<MyData> MyData { get; set; }
 
    void SaveChanges();
}

public interface IDoStuff
{
    void DoStuffQuickly();
}

Finally, we can implement the interfaces:

public class DataAccess : IDataAccess
{
    private readonly IMyDbContext _myDbContext;
 
    public DataAccess(IMyDbContext myDbContext)
    {
        _myDbContext = myDbContext;
    }
    public void AddData(List<string> newData)
    {
        foreach (var data in newData)
        {
            MyData myData = new MyData()
            {
                FieldOne = data
            };
            _myDbContext.MyData.Add(myData);
        }
        _myDbContext.SaveChanges();
    }
 
    public List<string> GetData()
    {
        List<string> data = 
            _myDbContext.MyData.Select(a => a.FieldOne).ToList();
 
        return data;
    }
}

The DbContext:

public class MyDbContext : DbContext, IMyDbContext
{
    public DbSet<MyData> MyData { get; set; }
 
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        string cn = @"Server=.\SQLEXPRESS;Database=test-db . . .";
        optionsBuilder.UseSqlServer(cn);
 
        base.OnConfiguring(optionsBuilder);
    }
 
    void IMyDbContext.SaveChanges()
    {
        base.SaveChanges();
    }
}

Let’s register a class to actually start the process:

public class DoStuff : IDoStuff
{
    private readonly IDataAccess _dataAccess;
    private readonly ILogger _logger;
 
    public DoStuff(IDataAccess dataAccess, ILogger logger)
    {
        _dataAccess = dataAccess;
        _logger = logger;
    }
 
    public void DoStuffQuickly()
    {
        _dataAccess.AddData(new List<string>()
        {
            "testing new data",
            "second test",
            "last test"
        });
 
        Parallel.For(1, 100, (a) =>
        {
            List<string> data = _dataAccess.GetData();
            foreach(string text in data)
            {
                _logger.Log(text);
            }
        });
    }
}

Now let’s register the types in out IoC container:

static void Main(string[] args)
{
    Console.WriteLine("Hello World!");
 
    UnityContainer container = new UnityContainer();
    container.RegisterType<IDataAccess, DataAccess.DataAccess>();
    container.RegisterType<IMyDbContext, MyDbContext>();
    container.RegisterType<IDoStuff, DoStuff>();
    container.RegisterType<ILogger, ConsoleLogger>();
 
    container.Resolve<IDoStuff>().DoStuffQuickly();
}

(Console logger is just a class that calls Console.WriteLine()).

Now, when you run it, you’ll get the same error as above (or something to the same effect).

To fix

One possible fix is to simply instantiate a DbContext as you need it; for example:

public List<string> GetData()
{
    using (var myDbContext = new MyDbContext())
    {
        List<string> data =
            myDbContext.MyData.Select(a => a.FieldOne).ToList();
        return data;
    }
    
}

However, the glaring problem that this creates is unit testing. The solution is a simple factory class:

public interface IGenerateDbContext
{
    IMyDbContext GenerateNewContext();
}

public class GenerateDbContext : IGenerateDbContext
{
    public IMyDbContext GenerateNewContext()
    {
        IMyDbContext myDbContext = new MyDbContext();
 
        return myDbContext;
    }
}

We’ll need to make the DbContext implementation disposable:

public interface IMyDbContext : IDisposable
{
    DbSet<MyData> MyData { get; set; }
 
    void SaveChanges();
}

And, finally, we can change the data access code:

public void AddData(List<string> newData)
{
    using (IMyDbContext myDbContext = _generateDbContext.GenerateNewContext())
    {
        foreach (string data in newData)
        {
            MyData myData = new MyData()
            {
                FieldOne = data
            };
            myDbContext.MyData.Add(myData);
        }
        myDbContext.SaveChanges();
    }
}
 
public List<string> GetData()
{
    using (IMyDbContext myDbContext = _generateDbContext.GenerateNewContext())
    {
        List<string> data =
            myDbContext.MyData.Select(a => a.FieldOne).ToList();
        return data;
    }
    
}

Now we can use IoC to generate the DBContext, and therefore it is testable, but we don’t pass the DbContext itself around, and therefore there are no threading issues.

Using Unity With Azure Functions

Azure Functions are a relatively new kid on the block when it comes to the Microsoft Azure stack. I’ve previously written about them, and their limitations. One such limitation seems to be that they don’t lend themselves very well to using dependency injection. However, it is certainly not impossible to make them do so.

In this particular post, we’ll have a look at how you might use an IoC container (Unity in this case) in order to leverage DI inside an Azure function.

New Azure Functions Project

I’ve covered this before in previous posts, in Visual Studio, you can now create a new Azure Functions project:

That done, you should have a project that looks something like this:

As you can see, the elephant in the room here is there are no functions; let’s correct that:

Be sure to call your function something descriptive… like “Function1”. For the purposes of this post, it doesn’t matter what kind of function you create, but I’m going to create a “Generic Web Hook”.

Install Unity

The next step is to install Unity (at the time of writing):

Install-Package Unity -Version 5.5.6

Static Variables Inside Functions

It’s worth bearing mind that a static variable works the way you would expect, were the function a locally hosted process. That is, if you write a function such as this:

[FunctionName("Function1")]
public static object Run([HttpTrigger(WebHookType = "genericJson")]HttpRequestMessage req, TraceWriter log)
{
    log.Info($"Webhook was triggered!");
    
    System.Threading.Thread.Sleep(10000);
    log.Info($"Index is {test}");
    return req.CreateResponse(HttpStatusCode.OK, new
    {
        greeting = $"Hello {test++}!"
    });
}

And access it from a web browser, or postman, or both as the same time, you’ll get incrementing numbers:

Whilst the values are shared across the instances, you can’t cause a conflict by updating something in one function while reading it in another (I tried pretty hard to cause this to break). What this means, then, is that we can store an IoC container that will maintain state across function calls. Obviously, this is not intended for persisting state, so you should assume your state could be lost at any time (as indeed it can).

Registering the Unity Container

One method of doing this is to use the Lazy object. This pretty much passed me by in .Net 4 (which is, apparently, when it came out). It basically provides a slightly neater way of doing this kind of thing:

private List<string> _myList;
public List<string> MyList
{
    get
    {
        if (_myList == null)
        {
            _myList = new List<string>();
        }
        return _myList;
    }
}

The “lazy” method would be:

public Lazy<List<string>> MyList = new Lazy<List<string>>(() =>
{
    List<string> newList = new List<string>();
    return newList;
});

With that in mind, we can do something like this:

public static class Function1
{
     private static Lazy<IUnityContainer> _container =
         new Lazy<IUnityContainer>(() =>
         {
             IUnityContainer container = InitialiseUnityContainer();
             return container;
         });

InitialiseUnityContainer needs to return a new instance of the container:

public static IUnityContainer InitialiseUnityContainer()
{
    UnityContainer container = new UnityContainer();
    container.RegisterType<IMyClass1, MyClass1>();
    container.RegisterType<IMyClass2, MyClass2>();
    return container;
}

After that, you’ll need to resolve the parent dependency, then you can use standard constructor injection; for example, if MyClass1 orchestrates your functionality; you could use:

_container.Value.Resolve<IMyClass1>().DoStuff();

In Practise

Let’s apply all of that to our Functions App. Here’s two new classes:

public interface IMyClass1
{
    string GetOutput();
}
 
public interface IMyClass2
{
    void AddString(List<string> strings);
}
public class MyClass1 : IMyClass1
{
    private readonly IMyClass2 _myClass2;
 
    public MyClass1(IMyClass2 myClass2)
    {
        _myClass2 = myClass2;
    }
 
    public string GetOutput()
    {
        List<string> teststrings = new List<string>();
 
        for (int i = 0; i <= 10; i++)
        {
            _myClass2.AddString(teststrings);
        }
 
        return string.Join(",", teststrings);
    }
}
public class MyClass2 : IMyClass2
{
    public void AddString(List<string> strings)
    {
        Thread.Sleep(1000);
        strings.Add($"{DateTime.Now}");
    }
}

And the calling code looks like this:

[FunctionName("Function1")]
public static object Run([HttpTrigger(WebHookType = "genericJson")]HttpRequestMessage req, TraceWriter log)
{
    log.Info($"Webhook was triggered!");
 
    string output = _container.Value.Resolve<IMyClass1>().GetOutput();
    return req.CreateResponse(HttpStatusCode.OK, new
    {
        output
    });
}

Running it, we get an output that we might expect:

References

https://github.com/Azure/azure-webjobs-sdk/issues/1206