我有一个数据库存储库界面:
public interface IDbRepository
{
Task<T> GetDataAsync<T>(Func<T, bool> filter = null) where T : class;
}
我有以下固定装置:
private List<Status> statusList = new List<Status> {
new Status { Name="Status A"},
new Status { Name="Status B"}
};
var repositoryMock = new Mock<IDbRepository>();
Func<Status, bool> filter = It.IsAny<Func<Status, bool>>();
repositoryMock.Setup(repository => repository.GetDataAsync(filter))
.ReturnsAsync(
() =>
{
//NEVER CALLED
if (filter == null)
return statusList.FirstOrDefault();
return statusList.FirstOrDefault(filter);
});
我使用以下测试:
[Fact]
public async Task Repository_GetDataAsync_Filter()
{
var repository = repositoryTestFixture.Ioc.Resolve<IDbRepository>();
Func<Status, bool> filter = stat => stat.Name == "Status A";
var res = await repository.GetDataAsync(filter);
//await task1.ContinueWith(ctask => Assert.NotNull(ctask.Result));
Assert.NotNull(res); //ALWAYS NULL!!!
}
我尝试调试,但是该方法从未调用过,因此我总是无法通过测试。
根据@Stephen Cleary,to call Wait()
或Result
不需要测试,而old official way自Visual Studio 2015起已弃用,异步测试是开箱即用。
Stephen Cleary•https://stephencleary.com/ 11个月前(2017-11-03 12:22:06 pm) 正如在 页面顶部,此解决方案是为VS2010设计的。 VS2015的作品 开箱即用,异步任务单元测试也可以。
我应该改变什么?
答案 0 :(得分:3)
使用It.IsAny<>()
是不正确的。它只能直接在Setup
表达式中使用。不在变量中。
当参数不匹配时,不调用模拟。因此,您将得到null。
在ReturnAsync
委托中访问传递的参数
var repositoryMock = new Mock<IDbRepository>();
repositoryMock
.Setup(repository => repository.GetDataAsync(It.IsAny<Func<Status, bool>>()))
.ReturnsAsync((Func<Status, bool> filter) => {//<-- grab passed argument here
if (filter == null)
return statusList.FirstOrDefault();
return statusList.FirstOrDefault(filter);
});
答案 1 :(得分:1)
我认为这里的问题是由于您的filter
局部变量引起的。通过创建不是表达式的变量,您实际上是在执行It.IsAny
调用并返回null。您可以想象,null
仅与null
函数匹配,这就是为什么看不到ReturnsAsync
被击中的原因。
请尝试内联该变量或将其类型更改为Expression<Func<Status, bool>>
,看看它是否按预期工作。
您必须始终牢记,模拟设置是使用表达式完成的,因此通常It.IsX
调用本身不会执行,只是作为表达式树进行分析和比较。