moqxunit.netautofixtureautomocking

AutoData Theories with AutoFixture using manual fakes


Given this system to test:

public class MySut
{
    private readonly IHardToMockDependency _hardToMockDependency;

    public MySut(IHardToMockDependency hardToMockDependency,
                 IOtherDependency otherDependency)
    {
        _hardToMockDependency = hardToMockDependency;
    }

    public string GetResult()
    {
        return _hardToMockDependency.GetResult();
    }
}

public interface IOtherDependency { }

public interface IHardToMockDependency
{
    string GetResult();
}

And this unit test:

internal class FakeHardToMockDependency : IHardToMockDependency
{
    private readonly string _result;

    public FakeHardToMockDependency(string result)
    {
        _result = result;
    }

    public string GetResult()
    {
        return _result;
    }
}

public class MyTests
{
    [Fact]
    public void GetResultReturnsExpected()
    {
        string expectedResult = "what I want";
        var otherDependencyDummy = new Mock<IOtherDependency>();
        var sut = new MySut(new FakeHardToMockDependency(expectedResult),
                            otherDependencyDummy.Object);

        var actualResult = sut.GetResult();

        Assert.Equal(expectedResult, actualResult);
    }
}

How should I convert it to use AutoFixture.Xunit and AutoFixture.AutoMoq (while still using the manual fake)?

In real-world tests, the manual fake would have a more complex interface and behavior. Note that I want to pass the anonymous variable (the expectedResult string) to the constructor of the manual fake.


Solution

  • There are already some good answers here, but I'd like to suggest a simpler alternative that involves slightly loosening the invariants of the FakeHardToMockDependency class. Make it public, and provide a way to assign the result that is decoupled from the constructor:

    public class FakeHardToMockDependency : IHardToMockDependency
    {
        private string _result;
    
        public FakeHardToMockDependency(string result)
        {
            _result = result;
        }
    
        internal string Result
        {
            get { return _result; }
            set { _result = value; }
        }
    
        public string GetResult()
        {
            return _result;
        }
    }
    

    Notice that I've added an internal property and removed the readonly keyword from the field.

    This enables you to refactor the original test to this:

    [Theory, AutoMoqData]
    public void GetResultReturnsExpected_AutoDataVersion(
        [Frozen(As = typeof(IHardToMockDependency))]FakeHardToMockDependency fake,
        MySut sut)
    {
        var expected = "what I want";
        fake.Result = expected;
    
        var actual = sut.GetResult();
    
        Assert.Equal(expected, actual);
    }
    

    For completeness, here's the AutoMoqDataAttribute code:

    public class AutoMoqDataAttribute : AutoDataAttribute
    {
        public AutoMoqDataAttribute()
            : base(new Fixture().Customize(new AutoMoqCustomization()))
        {
        }
    }