验证方法按顺序调用

时间:2015-10-02 11:08:43

标签: c# nunit moq verify

我有以下方法:

public async Task DeleteAmendment(int amendmentHeaderId, int userId)
{
    // Delete the corresponding version records.
    await _amendmentVersionService.DeleteForAmendmentAsync(amendmentHeaderId);

    // Delete the corresponding lifecycle records.
    await _amendmentLifecycleService.DeleteForAmendmentAsync(amendmentHeaderId);

    // Delete the amendment header record itself.
    await _amendmentHeaderService.DeleteAsync(amendmentHeaderId, userId);
}

我正在尝试验证方法是按顺序调用的。

我尝试过设置回调(见下文)

AmendmentVersionService.Setup(x => x.DeleteForAmendmentAsync(It.IsAny<int>()))
    .Callback(() => ServiceCallbackList.Add("AmendmentVersionService"));

AmendmentLifecycleService.Setup(x => x.DeleteForAmendmentAsync(It.IsAny<int>()))
    .Callback(() => ServiceCallbackList.Add("AmendmentLifecycleService"));

AmendmentHeaderService.Setup(x => x.DeleteAsync(It.IsAny<int>(), It.IsAny<int>()))
    .Callback(() => ServiceCallbackList.Add("AmendmentHeaderService"));

但该列表仅包含字符串“AmendmentVersionService”

有什么想法吗?

4 个答案:

答案 0 :(得分:0)

实现相同目标的一种方法是使用不同的概念进行3次测试,每次调用一次。它有点脏,但作为后备解决方案,它可以让你走出困境

第一个电话:

  • 设置调用2以抛出自定义类型TestException的例外。
  • 断言仅执行了呼叫
  • 期待TestException被抛出

第二次电话:

  • 设置调用3以抛出自定义类型TestException的例外。
  • 断言调用1和2
  • 期待TestException被抛出

第三次电话会议:

  • 设置所有呼叫以正常执行。
  • 断言第1,2和3号电话

答案 1 :(得分:0)

你可以使用continuation(下面),但实际上如果你需要知道这些事情按顺序发生,那么它们就不应该是异步操作。通常,您希望异步操作能够同时运行;

public async Task DeleteAmendment(int amendmentHeaderId, int userId)
{
    Task.Run(() =>
    {
        // Delete the corresponding version records.
        await _amendmentVersionService.DeleteForAmendmentAsync(amendmentHeaderId);
     }).ContinueWith(_ => 
     {
        // Delete the corresponding lifecycle records.
        await _amendmentLifecycleService.DeleteForAmendmentAsync(amendmentHeaderId);
     }).ContinueWith(_ => 
    {
        // Delete the amendment header record itself.
        await _amendmentHeaderService.DeleteAsync(amendmentHeaderId, userId);
    });
}

答案 2 :(得分:0)

你的问题是,你永远无法知道一个方法是否因前一个完成(等待)而被执行,或者你是否幸运地没有遇到竞争条件(没有等待的呼叫,或者没有ContinueWith)

您可以实际测试它的唯一方法是将默认的TaskScheduler替换为您自己的实现,这将对后续任务进行排队。如果后续任务被调用,那么您的代码是错误的。如果不是,那意味着该任务实际上是由于前一个任务完成而执行的。

我们已经在Testeroids完成了这项工作,这是一个朋友和我建立的测试框架。

通过这样做,您的自定义TaskScheduler可以在一个线程中顺序执行任务(以真正突出您可能遇到的时间轴问题)并记录已安排的任务以及哪些任务更旧。

如果你想做到这一点,你需要付出很多努力,但至少你明白这一点。

为了取代defaukt TaskScheduler,你可以从我们在Testeroids上所做的工作中获得灵感。

https://github.com/Testeroids/Testeroids/blob/c5f3f02e8078db649f804d94c37cdab3df89fed4/solution/src/app/Testeroids/TplTestPlatformHelper.cs

答案 3 :(得分:0)

感谢Stephen Brickner ...

我将所有调用同步化,这使得Moq的回调像梦一样。

感谢您的所有帮助,非常感谢!