NSubstitute中是否存在使用其实例模拟类的内置方法,除了少数方法?
在示例中,我想保留实例的整个功能,但检查是否使用特定参数调用方法。
实际上,我这样做
public class Wrapper: IInterface
{
public IInterface real;
public IInterface sub;
public void Wrapper(IIterface realInstance, IIterface nsubstitute)
{
real = realInstance;
sub = nsubstitute;
}
public void MethodThatShouldWorkAsAlways()
{
real.MethodThatShouldWorkAsAlways();
}
public intMethodToBeTested(int a)
{
return sub.MethodToBeTested();
}
}
之所以这样,我测试的东西足够复杂,我不能手动创建包装器,这非常耗时且容易出错。如果Nsubstitute允许这样的话会很好:
IIterface realMock = NSubstitute.Mock< IIterface>( new RealClass());
realMock.MethodThatShouldWorkAsAlways(); // regular logic
realMock.MethodToBeTested(4).Returns( 3); // overrides the method to always returns 3
但到目前为止我没有找到任何相关的文档。
答案 0 :(得分:1)
如果我正确理解你的情况,你有一个正在测试的类,它将IIterface
作为一个依赖项,你想确保你的类调用MethodToBeTested(int)
方法'重新测试。
这可以使用生成模拟的.ForPartsOf<T>()
方法来完成。这将生成“部分模拟”,除非您提供覆盖,否则将调用基础类实现。但是它有一个很大的要求:要覆盖(或确保被调用)的方法必须是virtual
(如果在基类中定义,则为abstract
。
一旦你有了模拟,那么你可以使用.Received()
断言模拟上的方法被调用(或者如果你使用.DidNotReceive()
则不被调用。)
如果您希望使用基本实现,则实际上不需要覆盖MethodToBeTested(int)
的行为。
以下是基于示例代码的具体示例:
对于依赖项,您有RealClass
实现接口IIterface
,并且您希望确保调用MethodToBeTested(int)
。所以那些看起来像这样:
public interface IIterface
{
void MethodThatShouldWorkAsAlways();
int MethodToBeTested(int a);
}
public class RealClass: IIterface
{
public void MethodThatShouldWorkAsAlways()
{ }
public virtual int MethodToBeTested(int a)
{ return a; }
}
然后你有了实际测试的类,它使用IIterface
作为依赖:
public class ClassThatUsesMockedClass
{
private readonly IIterface _other;
public ClassThatUsesMockedClass(IIterface other)
{
_other = other;
}
public void DoSomeStuff()
{
_other.MethodThatShouldWorkAsAlways();
_other.MethodToBeTested(5);
}
}
现在,您要测试DoSomeStuff()
实际调用MethodToBeTested()
,因此您需要创建SomeClass
的部分模拟,然后使用.Received()
进行验证被称为:
[Test]
public void TestThatDoSomeStuffCallsMethodToBeTested()
{
//Create your mock and class being tested
IIterface realMock = Substitute.ForPartsOf<RealClass>();
var classBeingTested = new ClassThatUsesMockedClass(realMock);
//Call the method you're testing
classBeingTested.DoSomeStuff();
//Assert that MethodToBeTested was actually called
realMock.Received().MethodToBeTested(Arg.Any<int>());
}