如何添加使用 Autofixture 创建的 Mock 的特定实现?

zlZ*_*mon 4 c# tdd xunit autofixture

我正在为类编写测试(让我们称之为Sut),它有一些通过构造函数注入的依赖项。对于这个类,我必须使用参数最多的构造函数,因此我使用了AutoMoqDataAttributeGreedy实现:

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

public class AutoMoqDataAttributeGreedy : AutoDataAttribute
{
    public AutoMoqDataAttributeGreedy() : base(new Fixture(new GreedyEngineParts()).Customize(new AutoMoqCustomization()))
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

我的 sut 的构造函数如下所示:

public class Sut(IInerface1 interface1, IInterface2 interface2, IInterface3 interface3)
{
    Interface1 = interface1;
    Interface2 = interface2;
    Interface3 = interface3;
}
Run Code Online (Sandbox Code Playgroud)

一个示例测试如下所示:

[Theory, AutoMoqDataAttributeGreedy]
public void SomeTest([Frozen]Mock<IInterface1> mock1 ,
                      Mock<IInterface2> mock2, 
                      Sut sut, 
                      SomOtherdata data)
{
    // mock1 and mock2 Setup omitted

    // I want to avoid following line
    sut.AddSpeficicInterfaceImplementation(new IInterface3TestImplementation());

    sut.MethodIWantToTest();

    //Assert omitted 
}
Run Code Online (Sandbox Code Playgroud)

问题是我需要一个特定的IInterface3for testing实现,我想避免Interface3TestImplementation只为我的单元测试向我的 SUT ( )添加一个方法,我也想避免重复代码,因为我必须在每个实例中添加这个实例测试。

是否有一种很好且简洁的方法可以为我的所有测试/使用 Autofixture 的特定测试添加此实现?

Emm*_*ook 5

使用您创建的 IFixture,您可以针对特定接口调用 .Register 并提供在随后使用该接口时要使用的对象。

例如

_fixture = new Fixture().Customize(new AutoMoqCustomization());
_fixture.Register<Interface3>(() => yourConcreteImplementation);
Run Code Online (Sandbox Code Playgroud)

您还可以使用模拟,然后在夹具上使用 .Freeze ,这样您就可以针对接口设置一些预期的调用,而无需完全具体的实例。您可以让 AutoFixture 为您创建默认实现并应用您配置的设置。

例如

var mockedInterface = _fixture.Freeze<Mock<Interface3>>();
mockedInterface
    .Setup(x => x.PropertyOnInterface)
    .Returns("some value");
Run Code Online (Sandbox Code Playgroud)


Mar*_*ann 5

如果您需要将此作为一次性测试进行,那么 Enrico Campidoglio 的答案就是您要走的路。

如果您需要这是在所有的单元测试通常情况下,你可以自定义Fixture一个TypeRelay

fixture.Customizations.Add(
    new TypeRelay(
        typeof(IInterface3),
        typeof(IInterface3TestImplementation));
Run Code Online (Sandbox Code Playgroud)

这将发生变化,fixture以便在IInterface3需要时,IInterface3TestImplementation将创建和使用的实例。