Ube*_*ace 6 c# unit-testing mocking nsubstitute
除了少数方法之外,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();
}
}
Run Code Online (Sandbox Code Playgroud)
这样做的原因是我正在测试足够复杂的东西,我不能简单地手动创建包装器,这既耗时又容易出错。如果 Nsubstitute 允许以下内容,那就太好了:
IIterface realMock = NSubstitute.Mock< IIterface>( new RealClass());
realMock.MethodThatShouldWorkAsAlways(); // regular logic
realMock.MethodToBeTested(4).Returns( 3); // overrides the method to always returns 3
Run Code Online (Sandbox Code Playgroud)
但到目前为止我没有找到任何文件来做这件事。
如果我正确理解您的情况,您正在测试一个类,它将作为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; }
}
Run Code Online (Sandbox Code Playgroud)
然后你就有了实际测试的类,它使用IIterface作为依赖项:
public class ClassThatUsesMockedClass
{
private readonly IIterface _other;
public ClassThatUsesMockedClass(IIterface other)
{
_other = other;
}
public void DoSomeStuff()
{
_other.MethodThatShouldWorkAsAlways();
_other.MethodToBeTested(5);
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您想要测试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>());
}
Run Code Online (Sandbox Code Playgroud)