Search code examples
c#dependency-injectionautofacfactoryxunit

xUnit test: How to mock a factory?


I have the follwing two classes ClassA and ClassB.

To focus on: ClassB implements a factory of ClassA.

I want to test ClassB. So how can I (or would you) mock a factory of ClassA, sothat ClassB can instantiate a mock of ClassA and access its mocked function .ReturnString()?

public class ClassA : IClassA
{
    readonly int _number;

    public ClassA(int number)
    {
        _number = number;
    }

    public string ReturnString()
    {
        return _number.ToString();
    }
}
public class ClassB : IClassB
{
    int _exampleValue;
    readonly Func<int, IClassA> _classAFactory;

    public ClassB(Func<int, IClassA> classAFactory)
    {
        _classAFactory = classAFactory;
    }

    public string ExampleFct()
    {
        _exampleValue = 5;
        IClassA classA = _classAFactory(_exampleValue)
        return classA.ReturnString();
    }
}
public class TestClassB
{ 
    [Fact]
    public void TestClassBReturnsCorrectString()
    {
        // Arrange
        var mockClassAFact = ???
        IClassB classB = new ClassB(mockClassAFact);
     
        // Act
        string aString = classB.ExampleFct();

        // Assert
        Assert.True(aString == "5");
    }
}

As I am using "Autofac" as a base for IoC there might be a specific solution for this?

Thank you for any help!


Solution

  • mock the dependency (interface) as desired and create a delegate for the "factory" when arranging the test

    [Fact]
    public void TestClassBReturnsCorrectString() {
        // Arrange
        
        string expected = "5"
        IClassA mockClassA = Mock.Of<IClassA>(_ => _.ReturnString() == expected);
    
        int value = 5;
        Func<int, IClassA> mockClassAFact = 
            number => number == value ? mockClassA : throw new InvalidArgumentException();
    
        IClassB subject = new ClassB(mockClassAFact);
     
        // Act
        string actual = subject.ExampleFct();
    
        // Assert
        Assert.True(actual == expected);
    }
    

    Note: The above example uses MOQ to mock the IClassA dependency and creates a factory delegate to be used to exercised the test.

    "Autofac" in this case is an implementation detail that has no actual bearing on this isolated unit test.