我正在尝试使用Moq和EF Core创建一个测试存储库,使用其异步方法(如AddAsync
和SaveChangesAsync
),但我没有取得丝毫成功......
我发现了很多很多博客文章(包括这里的问题),但对我来说没什么用。
例如,我从字面上复制了本文中的代码并尝试实现其引用:[https://fpnotebook.wordpress.com/2017/05/29/asp-net-core-testing-repositories-and-mocking-ef /]但问题始终相同,例如:
消息:Moq.MockException:
在模拟上预期调用一次,但是是0次:m => m.AddAsync(It.IsAny(),)
没有配置设置。
同样适用于SaveChangesAsync
。
这是我一直试图实现的示例代码:
//配置
dbSetMock.Setup(m => m.AddAsync(It.IsAny<T>), It.IsAny<CancellationToken>()))
.Callback ((T model, CancellationToken token) => {queryableList.Concat (new [] {model})}})
.Returns ((T model, CancellationToken token) => Task.FromResult((EntityEntry<T>) null));
//测试本身
[Fact]
public async void AddAsyncTest ()
{
var mockSet = new Mock <DbSet <Wine >> ();
var mockContext = new Mock <SQLContext> (_ options);
mockContext.Setup (m => m.Set <Wine> ()). Returns (mockSet.Object);
var service = new WineCommandRepository (mockContext.Object);
await service.Insert (new Wine
{
IdWine = 1,
Name = "Wine1"
});
mockContext.Object.SaveChanges ();
mockSet.Verify (m => m.AddAsync (It.IsAny <Wine>),
new CancellationToken ()), Times.Once ());
mockContext.Verify (m => m.SaveChanges (), Times.Once ());
}
我的代码没有什么特别之处,我使用了我一直用于同步存储库的东西,但这种情况对我来说是新的。
有没有人克服这个并有一些例子或建议分享?
答案 0 :(得分:1)
我怀疑这不起作用的原因是这个检查(我在问题中添加了缺失括号并删除了不必要的括号)将永远不会通过:
mockSet.Verify(m => m.AddAsync(It.IsAny<Wine>()), new CancellationToken()), Times.Once);
原因是Verify
正在检查方法是使用提供的参数调用的,而不是“等效”的,但正是你告诉它的(引用等于)。但是,Verify
被赋予了一个CancellationToken的新实例,并且没有可能的方式被测试的代码将返回CancellationToken的确切实例。
您需要使用It.IsAny<CancellationToken>()
,或者如果您将测试中的代码抽象而不是显式使用new CancellationToken()
,并通过测试设置提供,那么您可以将该特定实例提供给{{ 1}}。
虽然我在这里,但如果您不知道,我应该谨慎使用Verify
。看看this question未接受的答案和评论,然后是接受的答案。