Kje*_*lbe 1 c# mocking nsubstitute
我正在尝试使用ForPartsOf<...>()and then subst.Configure().MyMethod(...).Returns(...)or替换一个方法subst.When(x => x.MyMethod(..)).Returns(...),但在这两种情况下,realMyMethod都会被调用。我的印象是,这两个下Configure()和When()本来是要确保MyMethod()电话在“配置模式”时,使没有真正的通话将被制成。我错了吗?还是我做错了什么?
下面是我的(非常简化和名称更改的)代码。对于subst1and subst2,真正的NeedsMoreWork方法被调用 with 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);
}
Run Code Online (Sandbox Code Playgroud)
使用 NSubstitute 时,需要模拟/存根的成员virtual才能被覆盖。
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;
}
}
Run Code Online (Sandbox Code Playgroud)
NeedsMoreWork 现在可以根据需要存根
[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);
}
Run Code Online (Sandbox Code Playgroud)
请注意CAUTION注释。如果我们之前没有
Configure()在这里使用过,.NeedsMoreWork(...)那么真正的方法就会在我们有机会覆盖行为之前执行。在某些情况下,这可能不是问题,但如果有疑问,请确保Configure()先调用,以便 NSubstitute 知道您正在配置调用并且不想运行任何实际代码。(这仍然不能保证真正的代码不会运行——记住,NSubstitute 不会阻止非虚拟调用的执行。)该
Configure()方法仅在 NSubstitute 4.0 及更高版本中可用。对于 4.0 之前的版本,我们需要使用When .. DoNotCallBase
注意:强调我的