如何使用 AutoFixture AutoMoq

问题描述

假设我有以下代码示例:

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()}";
   }
}

我目前有一个如下所示的测试:

[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());
}

这工作正常,但存在需要在测试中手动创建 SUT 的问题。当我的代码依赖于需要在其中包含一些数据的属性,并且需要始终记住使用某个值初始化属性时,这就会成为一个问题(如 Foo.Prefix 的情况)。

理想情况下,我希望能够通过以下方式定义测试:

[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",Times.Once());
}

其中 SUT 是使用 mockBar 实例自动创建的,然后我可以在测试中进一步使用它。

上面的代码不起作用,因为它会自动模拟一个新实例 IBar,并且不允许我访问底层模拟对象。

我的 automoqDataAttribute 没有任何花哨的东西:

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

但我想如果为了实现这一点需要进行任何设置,它会在这里

有没有办法使用 AutoFixture automoq 将测试参数中定义的模拟类型自动注入 SUT?

解决方法

基于 following article,我建议重构您的测试

[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());
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...