Unit testing 在单元测试(Xunit-Moq)中模拟异步方法时获取NullReferenceException

Unit testing 在单元测试(Xunit-Moq)中模拟异步方法时获取NullReferenceException,unit-testing,async-await,moq,xunit,xunit.net,Unit Testing,Async Await,Moq,Xunit,Xunit.net,我在测试一个使用异步存储库方法的服务方法时遇到问题 存储库层 公共接口IRepo { 任务GetByIdAsync(字符串Id); 任务SaveAsync(模型); } 服务层 void进程(字符串Id) { var模型=_repo.GetByIdAsync(Id).Result; model.Field1=“更新”; _repo.SaveAsync(model.Wait(); } 针对服务层的单元测试 [事实] SUTServiceTest() { //安排 模型=新模型(); var m

我在测试一个使用异步存储库方法的服务方法时遇到问题

存储库层
公共接口IRepo
{
任务GetByIdAsync(字符串Id);
任务SaveAsync(模型);
}
服务层
void进程(字符串Id)
{
var模型=_repo.GetByIdAsync(Id).Result;
model.Field1=“更新”;
_repo.SaveAsync(model.Wait();
}
针对服务层的单元测试
[事实]
SUTServiceTest()
{
//安排
模型=新模型();
var mockRepo=Mock.Get(new Repo());
mockRepo.Setup(x=>x.GetByIdAsync(It.IsNotNull()))
.Returns(()=>Task.FromResult(model));
mockRepo.Setup(x=>x.SaveAsync(It.IsAny()))
.回调((obj)=>model=obj);
var _服务=新的SUTService(mockRepo);
//表演
_服务流程(“1”);
//断言
Assert.Equal(“更新”,model.Field1);
}
我在
\u repo.SaveAsync(model.await()处收到以下错误:

System.NullReferenceException-对象引用未设置为对象的实例


不确定我错过了什么。

这个答案的目的是从聊天讨论中获取有价值的信息

正如OP所说,在以下行抛出了一个
NullReferenceException

\u repo.SaveAsync(model.Wait();
在单元测试中,
\u repo
尝试以以下方式初始化:

var mockRepo=Mock.Get(new Repo());
那不是正确的方法。请检查
Mock.Get
,了解它应该在什么时候使用以及用于什么目的

\u repo
应按以下方式初始化:

var mockRepo=new Mock();

OP在更改模拟创建后有以下观察结果:

然而,我放松了回购构建的DI设置

简而言之:这就是重点。
无论何时对组件进行单元测试,您都会尝试模拟(简化和模拟)其所有依赖项。它需要依靠存根间谍来验证在某些情况下调用了其中的哪一个,但模拟对象的具体实现并不重要

在这种特殊情况下,这意味着服务层不希望依赖于具体的存储库实例。它只需要一个repo,它可以捕获调用参数并验证其调用


供参考:测试

  • :返回数据的简单代码
  • :一个可以走捷径的工作备选方案
  • 存根:带有预定义数据的自定义逻辑
  • Mock:带有期望值的自定义逻辑(交互式存根)
  • 垫片:运行时的自定义逻辑
  • 间谍侦听器记录呼叫

您能与我们分享一下
.await()
实现吗?@PeterCsala在测试中,我正在为等待的方法设置模拟。但是下面的参考是实现
public async Task repoancy(Model Model){await dbHelper.SaveAsync(Model).ConfigureAwait(false);}
My Bad,又是
.Wait()等待线程在执行后返回。更改此行:
var mockRepo=Mock.Get(new Repo())到此:
var mockRepo=new Mock()@PeterCsala,有效。谢谢然而,我放松了回购构建的DI设置。