我正在用NSubstitute模拟一个抽象类,并希望它的受保护虚拟方法被调用。
public abstract class A
{
protected virtual bool ProtectedMethod()
{
return true;
}
public bool PublicMethod()
{
return ProtectedMethod();
}
}
public class ATest
{
[Fact]
public void Test()
{
var anA = Substitute.For<A>();
var result = anA.PublicMethod();
Assert.True(result);
}
}
该测试在执行时失败。实际上,即使类不是抽象的,它也会失败。如果这是正常行为,该怎么办才能确保调用ProtectedMethod?
PS。如果该方法不是虚拟的,则它将按预期工作。
答案 0 :(得分:0)
正如评论中所指出的,be careful substituting for classes。我建议安装NSubstitute.Analyzers以在编译时解决类替换的问题。
此测试失败的原因是因为您要替换A
,所以要替换NSubstitute replaces all virtual implementations with substitute ones(通常返回default
,除非另有说明,在这种情况下为false
)
您可以使用partial substitute,它会默认保留现有的实现(即ProtectedMethod
将根据基本实现不断返回true
):
[Fact]
public void TestUsingPartialSub() {
var anA = Substitute.ForPartsOf<A>();
var result = anA.PublicMethod();
Assert.True(result);
}
“ ...应该怎么做才能确保调用ProtectedMethod?”
NSubstitute无法断言受保护的方法(它通过可公开访问的API起作用)。如果可能,您可以重构代码以使用策略模式注入受保护的行为。这将使代码更灵活(包括为测试注入不同行为的灵活性),但设计会稍微复杂一些。
public interface IProtectedMethod {
bool ProtectedMethod();
}
public class AA {
private readonly IProtectedMethod x;
public AA(IProtectedMethod x) {
this.x = x;
}
public bool PublicMethod() {
return x.ProtectedMethod();
}
}
public class AATest {
[Fact]
public void TestUsingStrategySub() {
var x = Substitute.For<IProtectedMethod>();
var anA = new AA(x);
anA.PublicMethod();
x.Received().ProtectedMethod();
}
}
(在本示例中,请原意命名,我试图使其与原始名称保持相似,以使逻辑的各个部分移到更清楚的位置。)