Search code examples
c#unit-testingmoq

Is there a generic way to use SetReturnsDefault in Moq


I have a data access interface looking roughly like this:

public interface IDataRepository
{
    DatabaseResult<Customer> GetAllCustomers();
    DatabaseResult<Report> GetAllReports();
    DatabaseResult<Order> GetAllOrders();
    [..] (there are many methods like this)
}

DatabaseResult is a public class that is used to attach some metadata to the returned information.

When I mock this interface I want every single method (I probably have > 100) to return an instance of DatabaseResult<WhatEverType>. Currently I need to call SetReturnsDefault for each type, e.g.

    var mockDb = new Mock<IDataRepository>();
    mockDb.SetReturnsDefault(new DatabaseResult<Customer>());
    mockDb.SetReturnsDefault(new DatabaseResult<Report>());
    mockDb.SetReturnsDefault(new DatabaseResult<Order>());

Is there a way to just tell Moq that when the return type of a method is DatabaseResult<SomeType> then always return a new instance DatabaseResult<SomeType>, regardless of what SomeType is?

Or maybe, even more generically, there is a way to tell Moq to always return a new instance if the return type is class/record/struct? And for common generic collection interfaces like IEnumerable<T>, IList<T>, IDictionary<T>, etc., just return a random .NET type that implements the interface?


Solution

  • Actually there is already general solution to your problem.

    You need to install two packages: AutoFixture and AutoFixture.AutoMoq.

    Classes included there allows for automatic mocking of interfaces.

    Please see example unit tests presenting how it can be used to autmatically mock all interface's methods:

    public class GenericType<T>
    {
        public T Value { get; set; }
    }
    
    public interface IInterface
    {
        GenericType<int> GetInt();
        GenericType<string> GetString();
        GenericType<object> GetObject();
    }
    
    public class AutoFixtureTests
    {
        [Fact]
        public void Test2()
        {
            // Arrange
            var fixture = new Fixture().Customize(new AutoMoqCustomization());
            var mock = fixture.Create<Mock<IInterface>>().Object;
    
            // Act & Assert
            Assert.NotNull(mock.GetInt());
            Assert.NotNull(mock.GetString());
            Assert.NotNull(mock.GetObject());
        }
    
        [Fact]
        public void Test()
        {
            // Arrange
            var fixture = new Fixture();
            var mock = fixture.Create<Mock<IInterface>>().Object;
    
            // Act & Assert
            Assert.Null(mock.GetInt());
            Assert.Null(mock.GetString());
            Assert.Null(mock.GetObject());
        }
    }