我想使用NSubstitute创建一个间谍,但是在经过大量的搜索和阅读文档后却找不到答案。
这个想法是用一个 overriden 方法代替,我可以用它来监视接收到的呼叫,等等。但是,如何使用NSubstitute实现此目标?
我不希望既不放松protected
也不放松abstract
修饰符。
这就是我想要做的:
[Test]
public void Items_Add_shouldCall_ItemAddedMethod()
{
var sut = Substitute.For<ItemsRepository>();
// how to configure???
sut.Items.Add(Substitute.For<IItem>());
sut.Received().ItemAdded(); // currently cannot do this
// ...
public abstract class ItemsRepository
{
public ObservableCollection<IItem> Items { get; set; }
= new ObservableCollection<IItem>();
// ...
protected abstract void ItemAdded();
}
答案 0 :(得分:2)
NSubstitute API依靠调用一种方法来配置其Returns
或检查Received()
调用,这意味着对于标准用途,我们只能处理可以通过公共API调用的调用(不包括protected
和private
成员)。问题的abstract
部分没有问题;最好将NSubstitute与可访问的abstract
成员一起使用。
尽管C#设计使我们无法直接与protected
成员进行交互,但NSubstitute仍会记录对这些成员的调用。我们可以使用"unofficial" .ReceivedCalls()
扩展名来检查这些内容:
public abstract class ItemsRepository {
public virtual void Add(int i) { ItemAdded(); }
protected abstract void ItemAdded();
}
public class Fixture {
[Fact]
public void CheckProtectedCall() {
var sub = Substitute.For<ItemsRepository>();
sub.When(x => x.Add(Arg.Any<int>())).CallBase();
sub.Add(42);
var called = sub.ReceivedCalls().Select(x => x.GetMethodInfo().Name);
Assert.Contains("ItemAdded", called);
}
}
其他选项包括创建派生类(如@Nkosi所指出的),或使成员internal
代替protected
,并使用InternalsVisibleTo
使成员可被您的测试代码访问(如果您选择后者,则建议安装NSubstitute.Analyzer,以帮助确保正确配置)。