2

我在我的测试中有以下结构,旨在测试是否使用正确的复杂参数对象调用某个日志,即使它引发异常,然后将其包装并通常进一步操作。logThing 有一个方法:

void AddEntry(LogEntry);

所以我使用 When..Do 让它抛出异常,

public void UnitTest()
{
    // Arrange
    ILogThing logThing = Substitute.For<ILogThing>()
    SystemUnderTest system = new SystemUnderTest(logThing);

    List<LogEntry> actualEntries = new List<LogEntry>();
    LogEntry expectedEntry = GetSomeTestData();

    logThing.When(
        lt => lt.AddEntry(Arg.Do<LogEntry>(r => actualEntries.Add(r)))).Do(
        call => { throw new InvalidOperationException("testMessage"); });

    // Act
    try
    {
        system.DoSomethingWhichLogs(someArgs)
    }
    catch(WrappedException ex)
    {
        // Assert
        Assert.AreEqual(1, actualEntries.Count);
        Assert.AreEqual(actualEntries[0], expectedEntry);
    }
}

但是,此设置不会发生对 Arg.Do() 的预期调用。

我在 catch 块中放置了一个断点,并使用 Visual Studio 的即时窗口在 logThing 上调用 RecievedCalls<>(),它确实记录了一次使用正确参数调用 logThing 的记录——这就是 Arg.Do似乎只在 When..Do 块完成后执行。显然,这意味着由于我正在投入When..Do,它永远不会到达它。

我真的没想到 NSubstitute 会以这种方式订购电话,这是预期的行为吗?如果是这样,我可以做些什么来测试这样的传入参数,还是应该将我的参数检查放入主 When..Do 块中(这使得它更难阅读)?

被测系统对异常做了各种处理,包括将其与 logEntry 一起包装,因此在一个测试中进行所有这些检查对我很有用 - 我确实考虑过将它分成两个单独的测试,但意识到如果我这样做了,我将无法轻易确定错误包装输出的来源(它可能是最初生成 logEntry 的部分,也可能是包装它的部分)而我可以检查以确保使用此模式logThing 正在接收我所期望的。不过,如果有更好的方法可以做到这一点,我当然愿意接受建议。

4

1 回答 1

2

When..Do 和 Arg.Do 的确切顺序没有定义,我不建议指望它,因为我想它可能会根据实现在版本之间发生变化。(如果您有充分的理由按特定顺序定义它,请将您的建议发布到用户组。)

如果您只想检查 logThing 是否收到了预期的 LogEntry,则可以使用 Arg.Is() 在事后检查参数:

logThing.Received().AddEntry(Arg.Is(expectedEntry));

如果您需要更复杂的比较逻辑,您可以做同样的事情,但使用一种方法来检查参数:

logThing.Received().AddEntry(Arg.Is<LogEntry>(x => CheckLogEntry(x)));

CheckLogEntry可以做任何你需要的检查,你可以像以前一样保持When..Do throwing。

如果您需要使用 When..Do 方法,您可以保留现有方法,但将参数的捕获移动到Do调用中以确保您期望的调用顺序:

logThing.When(
    lt => lt.AddEntry(Arg.Any<LogEntry>())).Do(
    call =>
    {
        actualEntries.Add(call.Arg<LogEntry>());
        throw new InvalidOperationException("testMessage");
    });

关于其他测试方法的建议,我并不完全清楚您在这里尝试做什么,但是如果您在隔离包装输出的来源时遇到问题,也许您可​​以将此责任转移到另一个依赖项?从这个测试的角度来看,这将使您可以替换这种依赖关系并准确控制发生的位置。

于 2011-09-29T09:45:15.867 回答