我今天遇到了一个奇怪的问题 - 我正在围绕SIM对象编写单元测试。它声称当更新SIM对象并且PIN尝试剩余已更改时,它将调用特定方法。测试看起来像这样:
[Test]
public void TestUpdateSimInfoWithPinAttemptsChangedCallsOnPinAttemptsRemaining()
{
var info = new SimPinInfo {PinAttemptsRemaining = 10};
var sim = new Mock<Sim>(info);
info.PinAttemptsRemaining = 2;
sim.Object.UpdateSimInfo(info);
sim.Verify(s => s.FireOnPinAttemptsRemaining(), Times.Once());
}
因此创建了模拟SIM对象,剩余10次PIN尝试。然后,SimPinInfo
对象在传递给PinAttemptsRemaining
方法之前将UpdateSimInfo()
值减少为2。
SIM构造函数(为清晰起见进行了修剪):
internal Sim(SimPinInfo info) : this()
{
_pinAttemptsRemaining = info.PinAttemptsRemaining;
_pukAttemptsRemaining = info.PukAttemptsRemaining;
......
}
UpdateSimInfo()
方法(修剪):
internal void UpdateSimInfo(SimPinInfo info)
{
lock(_locker)
{
if (_pinAttemptsRemaining != info.PinAttemptsRemaining)
{
Log("PinAttemptsRemaining changed");
_pinAttemptsRemaining = info.PinAttemptsRemaining;
FireOnPinAttemptsRemaining();
}
.....
}
}
一个非常简单的测试 - 应该发生的是上面的if语句为真(引脚尝试剩余已经改变),因此OnPinAttemptsRemaining
事件将被触发。但是,测试失败了(尽管不是所有的时间 - 当我慢慢地通过代码时它已经过去了!)。发生的事情是if语句是假的 - _pinAttemptsRemaining
和info.PinAttemptsRemaining
都是2.看来SIM模拟实际上并没有在预期时创建 - 当info.PinAttemptsRemaining
为10时。
为了证明这一点,我添加了评论:
var sim = new Mock<Sim>(info);
info.PinAttemptsRemaining = 2;
Console.WriteLine("SIM's pin attempts = " + sim.Object.PinAttemptsRemaining);
我还在SIM对象的构造函数中放了一个断点。单步执行Console.WriteLine
行而不是new Mock...
行时,会遇到断点。因此,在需要之前不会创建对象。
我认为这称为延迟加载或懒惰评估。
此行为有多种解决方法 - 我最终创建了一个新的SimPinInfo
对象以传递给UpdateSimInfo()
。
之前有没有人遇到过这种行为?我找不到任何引用。
答案 0 :(得分:2)
从我所读到的,你试图测试一个模拟。
sim.Object.UpdateSimInfo(info);
模拟意味着替换依赖项,您不使用它们来替换您要测试的代码。没有看到整个代码,我猜你甚至不需要Mock来测试这种行为。假设FireOnPinAttemptsRemaining引发了一个事件,我推荐这样的测试方法:
[Test]
public void TestUpdateSimInfoWithPinAttemptsChangedCallsOnPinAttemptsRemaining()
{
int eventFiredCount = 0;
var info = new SimPinInfo {PinAttemptsRemaining = 10};
var sim = Sim(info);
sim.OnPinAttemptsRemaining += (sender, e) => { eventFiredCount++; };
info.PinAttemptsRemaining = 2;
sim.UpdateSimInfo(info);
Assert.AreEqual(1, eventFiredCount);
}
我不是100%在事件处理程序上,因为我不知道Fire方法是否引发了事件,或事件名称,但它应该给你一个想法。