C# Autofac mock-如何从依赖项中的特定方法设置/伪造数据?
我对单元测试、Autofac和Mock都是新手,所以很可能,这相对容易,但我很难弄明白 我有一个类C# Autofac mock-如何从依赖项中的特定方法设置/伪造数据?,c#,moq,autofac,xunit,C#,Moq,Autofac,Xunit,我对单元测试、Autofac和Mock都是新手,所以很可能,这相对容易,但我很难弄明白 我有一个类systemundtest,它有一个依赖项,还有两个方法GetValueOne和GetValueTwo public class SystemUnderTest : ISystemUnderTest { private readonly IDependency _dependency; public SystemUnderTest(IDependency dependency)
systemundtest
,它有一个依赖项,还有两个方法GetValueOne
和GetValueTwo
public class SystemUnderTest : ISystemUnderTest
{
private readonly IDependency _dependency;
public SystemUnderTest(IDependency dependency)
{
_dependency = dependency;
}
public string GetValueOne()
{
return _dependency.GetValueOne();
}
public string GetValueTwo()
{
return _dependency.GetValueTwo();
}
}
public interface ISystemUnderTest
{
string GetValueOne();
string GetValueTwo();
}
这些方法从依赖项获取数据
public class Dependency : IDependency
{
public string GetValueOne()
{
return "get-value-one";
}
public string GetValueTwo()
{
return "get-value-two";
}
}
public interface IDependency
{
string GetValueOne();
string GetValueTwo();
}
我试图从其中一个方法(即“GetValueTwo
”)中伪造数据,因此它返回的是“预期值”
,而不是依赖项通常返回的“GetValueTwo”
[Fact]
public async Task Test_SystemUnderTest()
{
using (var mock = AutoMock.GetLoose())
{
// Setup
mock.Mock<IDependency>().Setup(x => x.GetValueTwo()).Returns("expected value");
// Configure
mock.Provide<IDependency, Dependency>();
// Arrange - configure the mock
var sut = mock.Create<SystemUnderTest>();
// Act
var actual_GetValueOne = sut.GetValueOne();
var actual_GetValueTwo = sut.GetValueTwo();
// Assert - assert on the mock
Assert.Equal("get-value-one", actual_GetValueOne);
Assert.Equal("expected value", actual_GetValueTwo);
}
}
[事实]
公共异步任务测试\u SystemUnderTest()
{
使用(var mock=AutoMock.GetLoose())
{
//设置
mock.mock().Setup(x=>x.GetValueTwo())。返回(“预期值”);
//配置
mock.Provide();
//排列-配置模拟
var sut=mock.Create();
//表演
var-actual_GetValueOne=sut.GetValueOne();
var actual_GetValueTwo=sut.GetValueTwo();
//Assert-在模拟上断言
Assert.Equal(“获取值一”,实际值一);
Assert.Equal(“预期值”,实际值二);
}
}
我测试的第一部分,设置,似乎没有任何效果,可能是因为我做了一些基本的错误
有人知道如何节省时间吗?不是编写单元测试的专家,但我非常确定,通过使用带有两个类型参数的
Provide
,您可以覆盖以前所做的设置部分。根据我的理解,应该使用Provide
方法来提供您自己的目标接口的模拟实现,因此对同一依赖项同时使用带有两个类型参数的Provide
和Setup
是没有意义的
因此,您可以修改依赖关系
实现的GetValueTwo
以返回的“期望值”
,并使用未修改的其余代码,也可以将模拟实例提供给提供
方法,其中包含一个类型参数,这两个方法都是以前设置的,如下所示:
[Fact]
public async Task Test_SystemUnderTest()
{
using (var mock = AutoMock.GetLoose())
{
var mockedDependency = mock.Mock<IDependency>();
// Setup
mockedDependency.Setup(x => x.GetValueOne()).Returns("get-value-one");
mockedDependency.Setup(x => x.GetValueTwo()).Returns("expected value");
// The following line is not even necessary
mock.Provide<IDependency>(mockedDependency.Object);
// Arrange - configure the mock
var sut = mock.Create<SystemUnderTest>();
// Act
var actual_GetValueOne = sut.GetValueOne();
var actual_GetValueTwo = sut.GetValueTwo();
// Assert - assert on the mock
Assert.Equal("get-value-one", actual_GetValueOne);
Assert.Equal("expected value", actual_GetValueTwo);
}
}
[事实]
公共异步任务测试\u SystemUnderTest()
{
使用(var mock=AutoMock.GetLoose())
{
var mockedDependency=mock.mock();
//设置
mockedDependency.Setup(x=>x.GetValueOne())。返回(“获取值一”);
mockedDependency.Setup(x=>x.GetValueTwo())。返回(“预期值”);
//下面的一行甚至不是必需的
mock.Provide(mockedDependency.Object);
//排列-配置模拟
var sut=mock.Create();
//表演
var-actual_GetValueOne=sut.GetValueOne();
var actual_GetValueTwo=sut.GetValueTwo();
//Assert-在模拟上断言
Assert.Equal(“获取值一”,实际值一);
Assert.Equal(“预期值”,实际值二);
}
}
依赖关系
实现的成员需要具有虚拟成员,以便在执行部分模拟时能够覆盖这些成员
public class Dependency : IDependency {
public virtual string GetValueOne() {
return "get-value-one";
}
public virtual string GetValueTwo() {
return "get-value-two";
}
}
然后,与另一个答案中的建议类似,您将模拟实现,确保使其能够调用基本成员,并且只设置需要覆盖的成员
public void Test_SystemUnderTest() {
using (var mock = AutoMock.GetLoose()) {
// Setup
var dependency = mock.Mock<Dependency>();
dependency.CallBase = true;
dependency.Setup(x => x.GetValueTwo()).Returns("expected value");
// Configure
mock.Provide<IDependency>(dependency.Object);
// Arrange - configure the mock
var sut = mock.Create<SystemUnderTest>();
// Act
var actual_GetValueOne = sut.GetValueOne();
var actual_GetValueTwo = sut.GetValueTwo();
// Assert - assert on the mock
Assert.AreEqual("get-value-one", actual_GetValueOne);
Assert.AreEqual("expected value", actual_GetValueTwo);
}
}
public void Test\u SystemUnderTest(){
使用(var mock=AutoMock.GetLoose()){
//设置
var dependency=mock.mock();
dependency.CallBase=true;
Setup(x=>x.GetValueTwo())。返回(“期望值”);
//配置
mock.Provide(dependency.Object);
//排列-配置模拟
var sut=mock.Create();
//表演
var-actual_GetValueOne=sut.GetValueOne();
var actual_GetValueTwo=sut.GetValueTwo();
//Assert-在模拟上断言
AreEqual(“获取值一”,实际值一);
Assert.AreEqual(“预期值”,实际值二);
}
}
如果需要模拟的实现成员可以被覆盖(即
virtual
),则上述操作将通过。configure/provide将覆盖设置。为什么要提供依赖性实现呢?我注意到了一些事情。如果没有等待,为什么测试是异步的?@Nkosi简化了这个问题的代码,忘记了删除异步测试。这是一个有趣的问题。我建议您注意我是如何编辑/重新格式化问题的,以便更好地阅读流程和理解您的问题。您可以完全删除“提供”,因为您已经在上设置了所有成员mock@Nkosi是的,刚刚测试过,在这种情况下,不需要提供all@JimmieAndersson实现的成员是虚拟的吗?@DejanJanjušević谢谢,但我不想在依赖接口上设置所有方法,因为我想在SystemUnderTest实现中使用/测试的其他方法中有很多逻辑。这就是为什么我试图提供IDependency的特定实现,所以它会使用这些方法,然后我只想设置特定的方法。@Nkosi它们不是虚拟的