覆盖 NSubstitute 中受保护的抽象方法
Overriding protected abstract method in NSubstitute
我想使用 NSubstitute 创建一个 spy,但在谷歌搜索和阅读文档后无法找到具体方法。
我的想法是用一个 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();
}
NSubstitute API 依赖于调用一个方法来配置它 Returns
或检查 Received()
调用,这意味着对于标准使用我们只能使用可以调用的调用通过 public 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);
}
}
其他选项包括创建派生的 class(正如@Nkosi 指出的那样),或者使成员 internal
而不是 protected
并使用 InternalsVisibleTo
来创建您的测试代码可访问的成员(如果您执行后者,我建议安装 NSubstitute.Analyzer 以帮助确保正确配置)。
我想使用 NSubstitute 创建一个 spy,但在谷歌搜索和阅读文档后无法找到具体方法。
我的想法是用一个 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();
}
NSubstitute API 依赖于调用一个方法来配置它 Returns
或检查 Received()
调用,这意味着对于标准使用我们只能使用可以调用的调用通过 public 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);
}
}
其他选项包括创建派生的 class(正如@Nkosi 指出的那样),或者使成员 internal
而不是 protected
并使用 InternalsVisibleTo
来创建您的测试代码可访问的成员(如果您执行后者,我建议安装 NSubstitute.Analyzer 以帮助确保正确配置)。