C# 如何使用Moq提供方法实现?

C# 如何使用Moq提供方法实现?,c#,nunit,integration-testing,moq,C#,Nunit,Integration Testing,Moq,我有几个方法的接口。我有这个接口的默认实现。出于集成测试的目的,我想创建一个模拟实现,如果调用其中一个方法,它将返回我的自定义值,否则返回默认实现。是否可以使用Moq,或者我应该自己创建一个简单的存根 范例 IInterface default = new DefaultImplementation(); var mock = new Mock<IInterface>(); mock.Setup(i => i.Method(It.IsAny<>())).Calls(

我有几个方法的接口。我有这个接口的默认实现。出于集成测试的目的,我想创建一个模拟实现,如果调用其中一个方法,它将返回我的自定义值,否则返回默认实现。是否可以使用Moq,或者我应该自己创建一个简单的存根

范例

IInterface default = new DefaultImplementation();
var mock = new Mock<IInterface>();
mock.Setup(i => i.Method(It.IsAny<>())).Calls(p => p==0 ? return 5 : default.Method(p););

TheMethodITest(mock.Object()); //if it calls the object with 0 then it should get 5, otherwise it should call the default object
IInterface default=新的DefaultImplementation();
var mock=new mock();
mock.Setup(i=>i.Method(It.IsAny()).Calls(p=>p==0?返回5:default.Method(p););
methodist(mock.Object())//如果它用0调用对象,那么它应该得到5,否则它应该调用默认对象

我不确定提供默认值或特定值的条件是什么。但是,听起来您想用
Delegator
设置一个模拟实例

public void MoqCanBeSetupWithDelegator()
{
    var mock = new Mock<IInterface>();
    Func<string, int> valueFunction = i => i == "true" ? 1 : default(int);
    mock.Setup(x => x.Method(It.IsAny<string>())).Returns(valueFunction);

    Assert.Equal(1, mock.Object.Method("true"));
    Assert.Equal(0, mock.Object.Method("anonymous"));
}

public interface IInterface
{
    int Method(string arg);
}
public void MoqCanBeSetupWithDelegator()
{
var mock=new mock();
Func valueFunction=i=>i==“true”?1:默认值(int);
mock.Setup(x=>x.Method(It.IsAny()).Returns(valueFunction);
Assert.Equal(1,mock.Object.Method(“true”);
Assert.Equal(0,mock.Object.Method(“匿名”);
}
公共接口接口
{
int方法(字符串arg);
}

如您所见,
返回
方法被重载,以接受表示模拟方法签名的返回值(
int
)或delegator。您可以使用
Func
替换实际实现-
int方法(string arg)

您可以通过将Mock设置为具体类并使用
As()
检索完成设置的基础
IInterface
。然后,您可以强制转换
mock.Object
来调用底层的具体对象:

  [Test]
  public void SomeTest()
  {
     var mock = new Mock<DefaultImplementation>().As<IInterface>();
     mock.Setup(i => i.Method(It.IsAny<int>()))
         .Returns<int>(p => p == 0 
                                 ? 5 
                                 : ((DefaultImplementation)mock.Object).Method(p));

     TheMethodITest(mock.Object);
  }
[测试]
公共测试()
{
var mock=new mock().As();
mock.Setup(i=>i.Method(It.IsAny()))
.Returns(p=>p==0
5.
:((DefaultImplementation)mock.Object).Method(p));
方法论者(模拟对象);
}
以下是我测试的其他设置,FWIW:

public interface IInterface
{
   int Method(int p);
}
public class DefaultImplementation : IInterface
{
   public int Method(int p)
   {
      return 6;
   }
}
[TestFixture]
public class SomeFixture
{
   public static void TheMethodITest(IInterface dep)
   {
      for (var i = 0; i < 10; i++)
      {
         Debug.WriteLine("{0}:{1}",i, dep.Method(i));
      }
   }
} 
公共接口接口
{
int法(int-p);
}
公共类DefaultImplementation:IInterface
{
公共整数方法(INTP)
{
返回6;
}
}
[测试夹具]
公共类设备
{
公共静态无效方法论者(界面部)
{
对于(变量i=0;i<10;i++)
{
Debug.WriteLine(“{0}:{1}”,i,dep.Method(i));
}
}
} 

你能提供一个代码示例吗?我不清楚你的意思,否则就回到默认实现。如果不调用此方法,什么时候可以触发此方法?@Ian在问题中添加了使用不存在的方法的示例。您可以通过将其拆分为多个测试来完全防止这种情况。很明显,使用某个输入测试单元会触发与其他输入不同的东西,因此可以将它们分开。@Jeroenvanevel,这是为了集成测试
methodist
将调用其他方法,并传递
i接口
,方法
method
将在不同的位置被多次调用。我们已经有了单元测试,现在我们希望看到所有的测试都能一起工作。而且,内联实现这个函数是不直观的。要实现这一点,需要在lambda表达式中指定参数的类型。例如
…返回((字符串i)=>i==“true”?1:默认值(int))(string i)
,编译器无法判断您试图调用哪个方法重载。如果该方法“返回”void怎么办?没有
Returns()
方法,那么…:(为什么不直接将
DefaultImplementation
插入到方法中,而不是将其包装在Moq中?@StuartLC:不需要使用
CallBase
?@JohnGietzen实际上,这样更容易:
new Mock(){CallBase=true}.As();