NSubstitute 使用 class 的真实实例作为替代,除了一种方法
NSubstitute use real instance of a class as substitute, except one method
NSubstitute 中是否有任何内置方法可以使用其实例模拟 class 除了少数方法?
在示例中,我想保留实例的全部功能,但检查是否使用特定参数调用方法。
我确实做到了
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
但到目前为止我还没有找到相关文档。
如果我对你的情况的理解正确,你有一个 class 你正在测试它以 IIterface
作为依赖项并且你想确保 MethodToBeTested(int)
方法是正在被您正在测试的 class 调用。
这可以使用 .ForPartsOf<T>()
生成模拟的方法来完成。这会生成一个 "partial mock",它将调用底层的 class 实现,除非您提供覆盖。不过,它有一个很大的要求:您想要覆盖(或确保被调用)的方法必须是 virtual
(或者 abstract
,如果在基础 class 中定义的话)。
获得模拟后,您可以使用 .Received()
断言模拟中的方法已被调用(或未被调用,如果您使用 .DidNotReceive()
)。
如果您希望使用基本实现,您实际上不需要覆盖 MethodToBeTested(int)
的行为。
这是一个基于您的示例代码的具体示例:
对于依赖项,您有一个实现接口 IIterface
的 RealClass
,并且您希望确保 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; }
}
然后你有你实际测试的 class,它使用 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>());
}
NSubstitute 中是否有任何内置方法可以使用其实例模拟 class 除了少数方法?
在示例中,我想保留实例的全部功能,但检查是否使用特定参数调用方法。
我确实做到了
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
但到目前为止我还没有找到相关文档。
如果我对你的情况的理解正确,你有一个 class 你正在测试它以 IIterface
作为依赖项并且你想确保 MethodToBeTested(int)
方法是正在被您正在测试的 class 调用。
这可以使用 .ForPartsOf<T>()
生成模拟的方法来完成。这会生成一个 "partial mock",它将调用底层的 class 实现,除非您提供覆盖。不过,它有一个很大的要求:您想要覆盖(或确保被调用)的方法必须是 virtual
(或者 abstract
,如果在基础 class 中定义的话)。
获得模拟后,您可以使用 .Received()
断言模拟中的方法已被调用(或未被调用,如果您使用 .DidNotReceive()
)。
如果您希望使用基本实现,您实际上不需要覆盖 MethodToBeTested(int)
的行为。
这是一个基于您的示例代码的具体示例:
对于依赖项,您有一个实现接口 IIterface
的 RealClass
,并且您希望确保 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; }
}
然后你有你实际测试的 class,它使用 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>());
}