我正在尝试使用 ForPartsOf<...>()
替换方法然后 subst.Configure().MyMethod(...).Returns(...)
或 subst.When(x => x.MyMethod(..)).Returns(...)
, 但在这两种情况下都是真正的 MyMethod
被调用。我的印象是Configure()
和 When()
应该确保 MyMethod()
调用是在“配置模式”下进行的,因此不会进行真正的调用。我错了吗?还是我做错了什么?
下面是我的(大大简化并更改了名称的)代码。对于两者 subst1
和 subst2
, 真正的 NeedsMoreWork
使用 item == null
调用方法.
public interface IMyClass
{
bool NeedsMoreWork(Item item, out Part part);
bool DoWork(Item item);
}
public class MyClass : IMyClass
{
private ILogger log;
public MyClass(ILogger log)
{
this.log = log;
}
public bool NeedsMoreWork(Item item, out Part part)
{
log.Debug($"Examining item {item.Id}");
part = null;
if (item.Completed())
{
log.Debug($"Item {item.Id} already completed.");
return false;
}
part = item.GetNextPart();
log.Debug($"Item {item.Id} needs work on part {part.Id}.");
return true;
}
public bool DoWork(Item item)
{
if (!item.NeedsMoreWork(item, out Part part))
return false;
log.Debug($"Starting work on part {part.Id}.");
// Do work on part.
log.Debug($"Work completed on part {part.Id}.");
return true;
}
}
[TestMethod]
public void TestDoWork()
{
// Version with Configure():
var subst1 = Substitute.ForPartsOf<MyClass>(Substitute.For<ILogger>());
subst1.Configure()
.NeedsMoreWork(Arg.Any<Item>(), out Arg.Any<Part>())
.Returns(false);
// Version with WhenForAnyArgs():
var subst2 = Substitute.ForPartsOf<MyClass>(Substitute.For<ILogger>());
subst2.WhenForAnyArgs(x => x.NeedsMoreWork(Arg.Any<Item>(), out Arg.Any<Part>())
.Returns(false);
}
最佳答案
使用 NSubstitute 时,要模拟/ stub 的成员需要是虚拟
才能被覆盖。
引用Partial subs and test spies
public class MyClass : IMyClass {
private readonly ILogger log;
public MyClass(ILogger log) {
this.log = log;
}
public virtual bool NeedsMoreWork(Item item, out Part part) { //<-- THIS IS NOW VIRTUAL
log.Debug($"Examining item {item.Id}");
part = null;
if (item.Completed()) {
log.Debug($"Item {item.Id} already completed.");
return false;
}
part = item.GetNextPart();
log.Debug($"Item {item.Id} needs work on part {part.Id}.");
return true;
}
public bool DoWork(Item item) {
if (!NeedsMoreWork(item, out Part part))
return false;
log.Debug($"Starting work on part {part.Id}.");
// Do work on part.
log.Debug($"Work completed on part {part.Id}.");
return true;
}
}
NeedsMoreWork
现在可以根据需要 stub
[TestMethod]
public void TestDoWork_Should_Return_False() {
//Arrange
var subject = Substitute.ForPartsOf<MyClass>(Substitute.For<ILogger>());
bool expected = false;
subject.Configure().NeedsMoreWork(Arg.Any<Item>(), out Arg.Any<Part>()).Returns(expected);
//Act
bool actual = subject.DoWork(new Item());
//Assert - FluentAssertions
actual.Should().Be(expected);
}
Note the CAUTION comment. If we had not used
Configure()
here before.NeedsMoreWork(...)
then the real method would have executed before we had a chance to override the behavior. In some cases this may not be a problem, but if in doubt make sure you callConfigure()
first so NSubstitute knows you are configuring a call and don’t want to run any real code. (This still does not guarantee real code will not run – remember, NSubstitute will not prevent non-virtual calls from executing.)The
Configure()
method is only available in NSubstitute 4.0 and above. For verisons prior to 4.0 we need to useWhen .. DoNotCallBase
注意:强调我的
关于c# - NSubstitute ForPartsOf...当调用真正的方法时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57996835/