NSubstitute,try catch 不适用于配置为抛出异常的异步方法

NSubstitute, try catch is not working on async method configured to throw an exception

我正在使用 NSubstitute 进行模拟和伪造。我正在使用 EF6 并希望设置数据库上下文的 SaveChangesAsync-Method 以引发异常:

context.SaveChangesAsync().Throws(new DbUpdateException("", SqlExceptionHelper.CreateSqlException(2627)));

在我的数据存储库的方法中调用 SaveChangesAsync,如下所示:

try
{
     var fromDatabase = await context.Entries.OfType<Document>().FirstOrDefaultAsync(d => d.Id == doc.Id);

      if (fromDatabase == null)
      {
           fromDatabase = new Document();
           context.Entries.Add(fromDatabase);
       }

       PatchEntity(fromDatabase, doc);

       await context.SaveChangesAsync();
   }
   catch (DbUpdateException ex)
   {
       var innerException = ex.InnerException as SqlException;

       if (innerException != null && innerException.Number == 2627)
       {
           errors.Add(new DbValidationError(nameof(doc.Name), "A entry with the same Name already exists under the selected parent."));
        }
    }

这是我的单元测试中的行:

var result = await repository.TryAddOrUpdateDocument(doc);

不幸的是,我的测试一直失败,原因是我的测试方法 (!) 抛出了异常,我正在尝试捕捉。添加一般异常捕获块也不起作用,根本没有捕获到异常。异常正在冒泡。

我的测试被声明为 "public async Task...",但将其简单地转换为 void 并在我的存储库的异步方法上调用 .Result 也无济于事。怎么回事?

我不能 100% 确定,但您可能面临这样的问题,即无法自然捕获 async with void return 类型抛出的异常。在此处阅读 "Avoid Async Void" 部分: https://msdn.microsoft.com/en-us/magazine/jj991977.aspx 即使不能解决您的问题,也值得一读...

我认为问题是异常是从原始调用中抛出的,而不是从返回的 Task 内部抛出的 described here

试试这样的:

Func<int> throwDbEx = () => { 
    throw new DbUpdateException("", SqlExceptionHelper.CreateSqlException(2627));
}; 
context.SaveChangesAsync().Returns(Task.Run(throwDbEx));