【发布时间】:2017-02-14 08:17:38
【问题描述】:
我创建了这个测试:
[TestFixture]
public class UsersTests
{
private Core.Kernel coreKernel;
private Core.Configuration.ICoreConfiguration coreConfiguration;
[SetUp]
public void SetUp()
{
this.coreConfiguration = NSubstitute.Substitute.For<Core.Configuration.ICoreConfiguration>();
this.coreKernel = NSubstitute.Substitute.For<Core.Kernel>(this.coreConfiguration);
this.coreKernel.Initialize();
}
[Test]
public void AddUserTest()
{
Core.Communication.Entities.UserIdentity receivedUserIdentity = new Core.Communication.Entities.UserIdentity("user1", "passwd1");
((Core.Communication.ICoreService)this.coreKernel).AddUserIdentity(receivedUserIdentity);
this.coreKernel.Received(100).AddUser(Arg.Is<Core.Identity.UserIdentity>(u => u.UserId.Equals(receivedUserIdentity.UserId)));
}
}
Core.Kernel 在哪里:
public partial class Kernel : Core.IKernel
{
public Kernel(Configuration.ICoreConfiguration configuration)
: this(configuration, null, Enumerable.Empty<Type>())
{
}
public Kernel(Configuration.ICoreConfiguration configuration, Communication.ICoreService service, IEnumerable<Type> producerTypes)
{
if (configuration == null)
throw new ArgumentException("configuration object must be provided", "configuration");
if (producerTypes.Any(t => !t.IsAssignableFrom(typeof(Core.Extensibility.AbstractProducerPlugin))))
throw new ArgumentException("All types must inherit from AbstractProducerPlugin", "plugins");
this.state = KernelState.initializing;
this.configuration = configuration;
this.service = service ?? this;
this.producerTypes = producerTypes;
this.backends = new Dictionary<Core.Identity.DomainIdentity, Backend.Infrastructure.IBackend>();
}
internal virtual void AddUser(Core.Identity.UserIdentity userIdentity) {...}
}
尽管如此,this.coreKernel.Received(100).AddUser(... 没有被调用 100 次,只有一次。我做错了什么?
我的意思是,我不想给AddUser 打 100 次电话。我正在检查 AddUser 应该被调用 100 次。所以,断言应该失败。
编辑
猜猜这段代码(Core.IKernel.AddUserIdentity(...) 实现):
public class Core.Kernel {
public override void Core.IKernel.AddUserIdentity(UserIdentity userIdentity) {
this.AddUser(userIdentity); <<----- AddUser(...) is called
}
}
我认为这个问题与:
-
Core.Kernel实现Core.IKernel。Core.IKernel有AddUserIdentity(...)方法。 - 我在嘲笑
Core.Kernel而不是在嘲笑Core.IKernel。 - 根据
Core.IKernel.AddUserIdentity(...)方法实现AddUser应该没达到。 -
AddUser是Core.Kernel的internal virtual方法。它不是任何方法接口的实现。
我想断言AddUser 在达到AddUserIdentity 时被调用一次。
关于模拟的其他问题:
-
For<T>其中 T 是一个具体的类 ->virtual方法被替换了吗?没有执行virtual方法? -
ForPartsOf<T>其中 T 是一个具体的类 -> 这个类的哪些部分被模拟了(virtual methods,重写的接口方法)?
【问题讨论】:
-
我无法从这段代码中判断为什么断言没有失败,但我想我应该提到你似乎正在替代
Core.Kernel,但想测试其中的一些逻辑。例如,您在替代上调用coreKernel.Initialise()和AddUserIdentity(...),如果它是virtual,则不会运行任何实际逻辑。您可能需要查看partial substitutes 上的文档以实现此目的。或者更好的是,重构设计以允许您新建一个真正的Core.Kernel并测试它与其依赖项的交互。 -
感谢大卫的 cmets。你能看一下帖子吗?我已经对其进行了编辑以添加一些细节。
标签: nsubstitute