C# 无法捕获xUnit中的InvalidOperationException

C# 无法捕获xUnit中的InvalidOperationException,c#,.net-core,entity-framework-core,xunit,C#,.net Core,Entity Framework Core,Xunit,在过去的一个小时里,我一直试图通过以下测试,但似乎无法成功: [事实] 公共异步void TestDetachedRecordsRentUpdatedWithoutIDS()的 { var options=new DbContextOptionsBuilder() .UseInMemoryDatabase(数据库名称:“不能使用银行信息更新分离的客户”) .选择; int clientID,bankInfoID; 使用(var context=newclientcontext(选项)) { va

在过去的一个小时里,我一直试图通过以下测试,但似乎无法成功:

[事实]
公共异步void TestDetachedRecordsRentUpdatedWithoutIDS()的
{
var options=new DbContextOptionsBuilder()
.UseInMemoryDatabase(数据库名称:“不能使用银行信息更新分离的客户”)
.选择;
int clientID,bankInfoID;
使用(var context=newclientcontext(选项))
{
var服务=新的ClientService(上下文);
var bankInfo=new bankInfo{RoutingNumber=“12345”};
var client=new client{FirstName=“Javier”,LastName=“Garcia”,BankInfo=BankInfo};
等待服务。保存(客户);
clientID=client.ID;
bankInfoID=client.BankInfo.ID;
}
使用(var context=newclientcontext(选项))
{
var服务=新的ClientService(上下文);
var bankInfo=new bankInfo{RoutingNumber=“Modified”};
var client=new client{ID=clientID,FirstName=“Modified”,BankInfo=BankInfo};
尝试
{
等待服务。保存(客户);
}
捕获(System.InvalidOperationException ex)
{
var expected=“实体类型“BankInfo”上的属性“ID”是键的一部分,因此无法修改或标记为已修改。”;
Assert.Contains(应为,例如Message);
}
}
}
我发现的问题是,我似乎无法捕捉异常。这是我每次运行测试的结果:

为了提供一点额外的上下文,当调用
ClientService::Save
时,它会调用一个名为
handledisconnectedenties
的方法,该方法在以下行运行时启动:

94:  _context.Entry(existingClient.BankInfo).CurrentValues.SetValues(client.BankInfo);

我确实理解异常的本质,但我不理解为什么我的测试无法捕获它。非常感谢您的任何见解

该问题是由于测试定义的
异步无效

public async void TestDetachedRecordsArentUpdatedWithoutIDs() { ...
异步void方法具有不同的错误处理语义。当从
异步任务
异步任务
方法中抛出异常时,将捕获该异常并将其放置在任务对象上。对于
async void
方法,没有
Task
对象,因此从
async void
方法抛出的任何异常都将直接在
SynchronizationContext
方法启动时处于活动状态的
SynchronizationContext
上引发

无法使用Catch捕获异步Void方法的异常

比如说

private async void ThrowExceptionAsync()
{
  throw new InvalidOperationException();
}

public void AsyncVoidExceptions_CannotBeCaughtByCatch()
{
  try
  {
    ThrowExceptionAsync();
  }
  catch (Exception)
  {
    // The exception is never caught here!
    throw;
  }
}
将测试改为使用
任务

public async Task TestDetachedRecordsArentUpdatedWithoutIDs() {

    //...

}

由于测试定义的
异步无效
,请参考问题

public async void TestDetachedRecordsArentUpdatedWithoutIDs() { ...
异步void方法具有不同的错误处理语义。当从
异步任务
异步任务
方法中抛出异常时,将捕获该异常并将其放置在任务对象上。对于
async void
方法,没有
Task
对象,因此从
async void
方法抛出的任何异常都将直接在
SynchronizationContext
方法启动时处于活动状态的
SynchronizationContext
上引发

无法使用Catch捕获异步Void方法的异常

比如说

private async void ThrowExceptionAsync()
{
  throw new InvalidOperationException();
}

public void AsyncVoidExceptions_CannotBeCaughtByCatch()
{
  try
  {
    ThrowExceptionAsync();
  }
  catch (Exception)
  {
    // The exception is never caught here!
    throw;
  }
}
将测试改为使用
任务

public async Task TestDetachedRecordsArentUpdatedWithoutIDs() {

    //...

}

Reference

您确定在try-catch块中的保存出错吗?您有另一个等待服务。保存(客户端);上面的内容不是由try-catch处理的。也许是那个人扔了所以你的测试从来没有断言…?@marko是的。在第二次调用中,我尝试将ID添加到
bankInfo
记录中,异常将停止触发,因此我确定它是环绕try-catch的ID。您确定try-catch块中的保存出错吗?您有另一个等待服务。保存(客户端);上面的内容不是由try-catch处理的。也许是那个人扔了所以你的测试从来没有断言…?@marko是的。在第二次调用中,我尝试将ID添加到
bankInfo
记录中,异常将停止触发,因此我确定它是围绕try-catch的ID。