Hayden
Hayden

Reputation: 2988

How to auto inject mocked types defined in test parameters into SUT using AutoFixture AutoMoq

Let's say that I have the following code example:

public interface IBar
{
   string GetMessage();
}

public class Foo
{
   private readonly IBar bar;

   public Foo(IBar bar)
   {
      this.bar = bar;
   }

   public string Prefix { get; set; }

   public string RetrieveMessage()
   {
      if (string.IsNullOrWhiteSpace(Prefix)) return string.Empty;
      return $"{Prefix} {this.bar.GetMessage()}";
   }
}

I currently have a test that looks like the following:

[Test, AutoMoqData]
public void TestThatIHaveToManuallyCreateSUT(Mock<IBar> mockBar)
{
   // Arrange
   mockBar.Setup(x => x.GetMessage()).Returns("World");
   Foo sut = new Foo(mockBar.Object)
   {
      Prefix = "Hello",
   };

   // Act
   var actual = sut.RetrieveMessage();

   // Assert
   Assert.AreEqual($"{sut.Prefix} World", actual);
   mockBar.Verify(x => x.GetMessage(), Times.Once());
}

Which works fine, but it has the issue of manually needing the SUT to be created in the test. This becomes a problem when I have code that depends on properties needing to have some data in them, and needing to always remember to initialize the property with some value (as is the case with Foo.Prefix).

Ideally, I'd like to be able to define the test in the following way:

[Test, AutoMoqData]
public void TestWhereAutoDataCreatesTheSUT(Mock<IBar> mockBar, Foo sut)
{
   // Arrange
   mockBar.Setup(x => x.GetMessage()).Returns("World");

   // Act
   var actual = sut.RetrieveMessage();

   // Assert
   Assert.AreEqual($"{sut.Prefix} World", actual);
   mockBar.Verify(x => x.GetMessage(), Times.Once());
}

Where the SUT is automatically created with the mockBar instance, and I can then use it further in the test.

The code above doesn't work as it will auto mock a new instance IBar, and not give me access to the underlying mock object.

I don't have anything fancy in my AutoMoqDataAttribute:

public class AutoMoqDataAttribute : AutoDataAttribute
{
   public AutoMoqDataAttribute() : base(() => new Fixture().Customize(new AutoMoqCustomization() { ConfigureMembers = true }))
   {
   }
}

But I would figure if there's any setup that needs to happen in order to achieve this, it would be here.

Is there a way to auto inject mocked types defined in test parameters into SUT using AutoFixture AutoMoq?

Upvotes: 1

Views: 744

Answers (1)

Nkosi
Nkosi

Reputation: 247018

Based on the following article I would suggest refactoring your test

[Test, AutoMoqData]
public void TestWhereAutoDataCreatesTheSUT([Frozen]IBar bar, Foo sut) {
    // Arrange
    Mock<IBar> mockBar = Mock.Get(bar);
    mockBar.Setup(x => x.GetMessage()).Returns("World");

    // Act
    var actual = sut.RetrieveMessage();

    // Assert
    Assert.AreEqual($"{sut.Prefix} World", actual);
    mockBar.Verify(x => x.GetMessage(), Times.Once());
}

Upvotes: 1

Related Questions