Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在单元测试中,当使用nSubstitute和Autofixture作为DI容器时,如何获得模拟对象?_C#_Unit Testing_Dependency Injection_Autofixture_Nsubstitute - Fatal编程技术网

C# 在单元测试中,当使用nSubstitute和Autofixture作为DI容器时,如何获得模拟对象?

C# 在单元测试中,当使用nSubstitute和Autofixture作为DI容器时,如何获得模拟对象?,c#,unit-testing,dependency-injection,autofixture,nsubstitute,C#,Unit Testing,Dependency Injection,Autofixture,Nsubstitute,我曾经在单元测试中使用Moq和AutoMoqer,但我的团队决定改为NSubstitute。我们大量使用DI,所以我希望能够要求一个目标进行测试,并让该目标自动将所有模拟对象提供给其构造函数,或者换句话说,一个在模拟中传递的DI容器。我还想根据需要修改这些模拟对象 使用Moq/AutoMoq/MSTest的示例 [TestMethod] public void ReturnSomeMethod_WithDependenciesInjectedAndD1Configured_ReturnsConf

我曾经在单元测试中使用Moq和AutoMoqer,但我的团队决定改为NSubstitute。我们大量使用DI,所以我希望能够要求一个目标进行测试,并让该目标自动将所有模拟对象提供给其构造函数,或者换句话说,一个在模拟中传递的DI容器。我还想根据需要修改这些模拟对象

使用Moq/AutoMoq/MSTest的示例

[TestMethod]
public void ReturnSomeMethod_WithDependenciesInjectedAndD1Configured_ReturnsConfiguredValue()
{
    const int expected = 3;
    var diContainer = new AutoMoq.AutoMoqer();

    var mockedObj = diContainer.GetMock<IDependency1>();
    mockedObj
        .Setup(mock => mock.SomeMethod())
        .Returns(expected);

    var target = diContainer.Resolve<MyClass>();
    int actual = target.ReturnSomeMethod();

    Assert.AreEqual(actual, expected);
}

public interface IDependency1
{
    int SomeMethod();
}

public interface IDependency2
{
    int NotUsedInOurExample();
}

public class MyClass
{
    private readonly IDependency1 _d1;
    private readonly IDependency2 _d2;

    //please imagine this has a bunch of dependencies, not just two
    public MyClass(IDependency1 d1, IDependency2 d2)
    {
        _d1 = d1;
        _d2 = d2;
    }

    public int ReturnSomeMethod()
    {
        return _d1.SomeMethod();
    }
}
[TestMethod]
public void ReturnSomeMethod_带有dependenciesinjected和d1 configured_ReturnsConfiguredValue()
{
预期常数int=3;
var diContainer=new AutoMoq.AutoMoqer();
var mockedObj=diContainer.GetMock();
mockedObj
.Setup(mock=>mock.SomeMethod())
.回报(预期);
var target=diContainer.Resolve();
int actual=target.ReturnSomeMethod();
断言.AreEqual(实际、预期);
}
公共接口IDependency1
{
int SomeMethod();
}
公共接口IDependency2
{
int NotUsedInOurExample();
}
公共类MyClass
{
私有只读IDependency1_d1;
私有只读IDependency2\u d2;
//请想象一下,这有很多依赖项,而不仅仅是两个
公共MyClass(IDependency1 d1,IDependency2 d2)
{
_d1=d1;
_d2=d2;
}
public int returnsomethod()
{
返回_d1.SomeMethod();
}
}
由于我的问题措词不当,并且我进行了更多的研究,因此我找到了一种使用NSubstitute/AutofacContrib.NSubstitute/XUnit实现此功能的方法:

[Fact]
public void ReturnSomeMethod_WithDependenciesInjectedAndD1Configured_ReturnsConfiguredValue()
{
    const int expected = 3;
    var autoSubstitute = new AutoSubstitute();
    autoSubstitute.Resolve<IDependency1>().SomeMethod().Returns(expected);

    var target = autoSubstitute.Resolve<MyClass>();
    int actual = target.ReturnSomeMethod();

    Assert.Equal(actual, expected);
}

public interface IDependency1
{
    int SomeMethod();
}

public interface IDependency2
{
    int NotUsedInOurExample();
}

public class MyClass
{
    private readonly IDependency1 _d1;
    private readonly IDependency2 _d2;

    //please imagine this has a bunch of dependencies, not just two
    public MyClass(IDependency1 d1, IDependency2 d2)
    {
        _d1 = d1;
        _d2 = d2;
    }

    public int ReturnSomeMethod()
    {
        return _d1.SomeMethod();
    }
}
[事实]
public void ReturnSomeMethod_带有dependenciesinjected和d1 configured_ReturnsConfiguredValue()
{
预期常数int=3;
var autoSubstitute=新的autoSubstitute();
autoSubstitute.Resolve().SomeMethod()返回(预期);
var target=autoSubstitute.Resolve();
int actual=target.ReturnSomeMethod();
断言。相等(实际、预期);
}
公共接口IDependency1
{
int SomeMethod();
}
公共接口IDependency2
{
int NotUsedInOurExample();
}
公共类MyClass
{
私有只读IDependency1_d1;
私有只读IDependency2\u d2;
//请想象一下,这有很多依赖项,而不仅仅是两个
公共MyClass(IDependency1 d1,IDependency2 d2)
{
_d1=d1;
_d2=d2;
}
public int returnsomethod()
{
返回_d1.SomeMethod();
}
}

我还有我原来的问题。如何将AutoFixture.AutoNSubstitute用作DI容器来实现这一点

当您调用
Autofixture
依赖项注入容器时,我有点困惑。事实并非如此

AutoFixture
只是生成您在当前测试中不关心的值/实例,但它们不能保存默认值

在您的例子中,您正确地创建了
IPromise
的mock,但测试中的类不知道这一点。AutoFixture已生成“自己的”实例,并将其传递给测试中的类

您应该手动创建被测试类的实例 -因为您需要完全控制所有依赖项 -出于文档的原因,其他开发人员可以从中了解对象是如何创建的

您可以对在特定测试中不关心的依赖项使用AutoFixture,但为了使测试下的类正常工作,此依赖项应该返回一些值(不是null或默认值)

//排列
var fixture=新fixture();
var input=fixture.Create();//将生成一些整数值
var expected=fixture.Create();
var dummyDependency=fixture.Create();//在这次考试中,我不在乎
var requiredDependency=Substitute.For();//测试中需要依赖项
//仅当“输入”给定时才返回“预期”
RequiredDependence.SomeFunction(输入)。返回(预期);
var classUnderTest=新的classUnderTest(需要依赖性,依赖性二);
//表演
var实际值=classUnderTest.Convert(输入);
//断言
实际值应为(预期值);
对于多个测试,您可以引入一些工厂类,这些工厂类创建测试下类的实例,并将使用过的依赖项作为公共属性公开,这样您就可以在测试中访问它们。
或者使用依赖项作为测试类的私有成员,这样所有测试都可以访问它们

当然,AutoFixture提供了配置可能性。因此,您可以配置为在fixture请求某些类型时始终返回“您的”mock

var fixture = new Fixture();

var myMock = Substitute.For<IPromise>();
myMock.SomeFunction().Returns(default(ReturnClass)) // default value is null

// Configure fixture to always return your mock
fixture.Register<IPromise>(() => myMock);

var classUnderTest = fixture.Create<ClassUnderTest>();

// Execute test
var fixture=newfixture();
var myMock=Substitute.For();
myMock.SomeFunction().Returns(默认值(ReturnClass))//默认值为null
//将fixture配置为始终返回模拟
fixture.Register(()=>myMock);
var classUnderTest=fixture.Create();
//执行测试

但是,在使用AutoFixture创建测试中的类时应该小心,因为AutFixture会为所有公共属性生成随机值,这可能是不需要的,因为在测试中,您需要完全控制测试中的类。

您可以将AutoFixture转换为具有各种动态模拟库的,包括替代品

重写OP测试非常简单,如下所示:

[Fact]
public void ReturnSomeMethod_UsingAutoFixtureAutoNSubstitute()
{
    const int expected = 3;
    var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());
    fixture.Freeze<IDependency1>().SomeMethod().Returns(expected);

    var target = fixture.Create<MyClass>();
    var actual = target.ReturnSomeMethod();

    Assert.Equal(actual, expected);
}
[事实]
public void ReturnSomeMethod\u使用自动修复Autonsubstitute()
{
预期常数int=3;
var fixture=new fixture().Customize(new AutoNSubstituteCustomization());
fixture.Freeze().SomeMethod()返回(预期);
var target=fixture.Create();
var-actual=target.ReturnSomeMethod();
断言。相等(实际、预期);
}
在这里,我使用了MSTest,而不是MSTest,但是翻译它应该很简单

这里的关键是
Freeze
方法,它本质上将类型参数的生存期从瞬态更改为单例。这意味着在调用
Freeze
后,该特定
Fixture
实例必须创建一个
IDependency
对象的所有其他时间,它将重用它冻结的对象

Freeze
还返回刚冻结的对象,wh
[Fact]
public void ReturnSomeMethod_UsingAutoFixtureAutoNSubstitute()
{
    const int expected = 3;
    var fixture = new Fixture().Customize(new AutoNSubstituteCustomization());
    fixture.Freeze<IDependency1>().SomeMethod().Returns(expected);

    var target = fixture.Create<MyClass>();
    var actual = target.ReturnSomeMethod();

    Assert.Equal(actual, expected);
}