Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在构造函数中使用延迟加载的Moq_C#_Unit Testing_Moq_Lazy Loading_Lazy Evaluation - Fatal编程技术网

C# 在构造函数中使用延迟加载的Moq

C# 在构造函数中使用延迟加载的Moq,c#,unit-testing,moq,lazy-loading,lazy-evaluation,C#,Unit Testing,Moq,Lazy Loading,Lazy Evaluation,今天我遇到了一个奇怪的问题——我在写一个SIM对象的单元测试。它断言,当SIM对象被更新并且剩余的PIN尝试已更改时,它将调用特定的方法。测试如下所示: [Test] public void TestUpdateSimInfoWithPinAttemptsChangedCallsOnPinAttemptsRemaining() { var info = new SimPinInfo {PinAttemptsRemaining = 10}; var sim = new Mock&

今天我遇到了一个奇怪的问题——我在写一个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());
}
以及
UpdateSimInfo()
方法(修剪):

一个非常简单的测试-应该发生的是上面的if语句为true(剩余的pin尝试已更改),因此将触发
OnPinAttemptsRemaining
事件。但是,测试失败了(虽然不是每次都失败——当我慢慢地完成代码时,它就通过了!)。发生的情况是if语句为false-
\u pinAttemptsRemaining
info。pinAttemptsRemaining
均为2。当
info.PinAttemptsRemaining
为10时,SIM mock似乎并未按预期实际创建

为了证明这一点,我添加了一条评论:

var sim = new Mock<Sim>(info);
info.PinAttemptsRemaining = 2;
Console.WriteLine("SIM's pin attempts = " + sim.Object.PinAttemptsRemaining);
var-sim=新模拟(信息);
info.PinAttemptsRemaining=2;
Console.WriteLine(“SIM卡的pin尝试数=“+SIM.Object.PinAttemptsMaining”);
我还在SIM对象的构造函数中放置了一个断点。当跨过
控制台.WriteLine
行,而不是
新建模拟…
行时,遇到了断点。因此,直到需要时才创建对象

我相信这就是所谓的延迟加载或延迟评估

这种行为有多种解决方法-我最终创建了一个新的
SimPinInfo
对象来传递给
UpdateSimInfo()


以前有人见过这种行为吗?我找不到对它的任何引用。

从我读到的内容来看,您正在尝试测试一个模拟

sim.Object.UpdateSimInfo(info);
mock是用来替换依赖项的,而不是用来替换要测试的代码。在没有看到整个代码的情况下,我猜您甚至不需要模拟来测试这种行为。假设FireOnPinAttemptsMaining引发了一个事件,我建议对测试方法使用类似这样的方法:

[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);
}

我不完全了解事件处理程序,因为我不知道Fire方法是否正在引发事件,也不知道事件名称,但它应该能让您有所了解。

谢谢Steve。我从单元测试开始,单元测试实际上是在另一个线程上等待事件,使用监视器等。下一步看起来像你的代码,工作正常,最后我在问题中使用了模拟代码。我可能会回到你的风格,但是你能解释一下“替换依赖项/替换代码”的注释吗。干杯。也许是最简单的解释方式。假设您有一个包装数据访问的服务。数据服务。它直接与您的数据库通信。您还有其他使用DataService检索和保存信息的代码。现在,您需要测试从DataService获取数据所需的一些代码。mock允许您通过模拟数据服务,在与数据服务隔离的情况下测试该代码。例如,我将为数据服务提供一个名为IDataService的契约接口。通过使用Mock,您可以在不需要“真实”数据连接的情况下设置预期场景。
sim.Object.UpdateSimInfo(info);
[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);
}