【问题标题】:Moq / Unit Test Unable to Catch Exception unless stepping through code起订量/单元测试无法捕获异常,除非单步执行代码
【发布时间】:2014-10-14 11:12:10
【问题描述】:

我有一个单元测试,它期望一个异常作为返回参数。

如果我通过调试器运行代码,并检查它工作的各种元素。 如果我只运行所有测试,它不会。

问题必须与该方法是异步的事实有关,就好像我删除了它作为expexted 工作的各种异步元素一样。 (我猜是时间问题)

我的单元测试是;

  [TestMethod]
  [ExpectedException(typeof(System.AggregateException))]
  public void Service_GetDoc_ThrowsExceptionIfNull()
  {
        var nullRepository = new Mock<CCLDomainLogic.Repositories.DocRepository>();
        IDD emptyDoc = null;

        nullRepository
          .Setup<Task<CCLDomainLogic.DomainModels.Doc>>
          (x => x.GetDocAsync(It.IsAny<int>()))
          .Returns(() => Task<CCLDomainLogic.DomainModels.Doc>.Factory.StartNew(() => emptyDoc));

        DocService s = new DocService(nullRepository.Object);

        var foo = s.GetDocAsync(1).Result;
    }            

还有代码(简称是)

    public async Task<Doc> GetDocAsync(int id)
    {
        Stopwatch timespan = Stopwatch.StartNew();
        try
        {
            ...                
            {
                var t = await Task.Run(() => _repository.GetDocAsync(id));
                ...
            }
            timespan.Stop();

            if (t == null)
            {
                throw new ArgumentNullException("DocService.GetDocAsync returned Null Document");
            }

        }
        catch (Exception e)
        {
            throw new Exception("Error in DocService.GetDocAsync", e);
        }
    }

那么在运行异步时我该如何重新设计这个测试来捕捉异常。 作为一个额外的问题,我可以修改我的单元测试,以便我可以检查特定异常,而不是聚合异常吗?

【问题讨论】:

  • 如果没有看到所有代码就很难判断——从我所见,我认为你首先不需要异步,因为你开始一个任务只是为了等待它——为什么难道你不只是使用_repository.GetDocAsync(id) 并且只在必要时才进入线程吗?
  • 嗯,异步/任务的东西是我从别处复制的东西,我会回去重新阅读以确保我使用它正确。我的起订量确保存储库返回 null,并引发异常,我只是无法理解它不会传播到单元测试。
  • 据我所见,它应该等待(.Result 部分)-但... 中可能还有更多内容-除此之外,您真的不需要像 await Task.Run(... 这样的东西,如果您不想使用取消或超时
  • 谢谢。将测试方法更改为异步,并将最后一行更改为 await s.GetDocAsync(1);做到了。现在让我们希望,当我完成并删除我开始的一些额外任务时,不会有任何其他问题:-)
  • 改用var t = await _repository.GetDocAsync(id);

标签: c# visual-studio unit-testing moq


【解决方案1】:

您的测试运行在断言已经运行(或未运行)之后执行的异步代码的原因。 使用调试器只会给异步代码更多的工作时间。 为了测试您的代码,您只需将 MTest 的返回类型更改为 Task 并将 await 添加到相关调用中:

[TestMethod]
[ExpectedException(typeof(System.AggregateException))]
public async Task Service_GetDoc_ThrowsExceptionIfNull()
{
    var nullRepository = new Mock<CCLDomainLogic.Repositories.DocRepository>();
    IDD emptyDoc = null;

    nullRepository
        .Setup<Task<CCLDomainLogic.DomainModels.Doc>>(x => x.GetDocAsync(It.IsAny<int>()))
        .Returns(() => Task<CCLDomainLogic.DomainModels.Doc>.Factory.StartNew(() => emptyDoc));

    DocService s = new DocService(nullRepository.Object);

    var foo = await s.GetDocAsync(1).Result;
}  

【讨论】:

  • 也许没有.Result
猜你喜欢
  • 2014-09-29
  • 1970-01-01
  • 1970-01-01
  • 2016-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多