![](/img/trans.png)
[英]How to Unit Test Repository Method That Takes Lambda Expression as A Parameter
[英]How to unit test the expression being passed into the repository layer
我有一个服务层,该服务层调用存储库层来获取数据,然后对返回对象进行处理。 我想测试被发送到存储库“ get”方法中的表达式,以防万一主键变成复合键之类的东西。
例:
public async Task ArchiveAsync(Domain.Person person)
{
Data.Person entityModel = await _repo.SingleOrDefaultAsync<Data.Person>(p => p.Id == person.Id);
// Stuff is done here...
}
因此,在此示例中,传递了域对象,获取了数据对象,并对其进行了处理。 我想测试传递到SingleOrDefaultAsync
方法中的表达式。
思考?
最好重构代码,并使“表达式”成为适当的实体。 规范模式非常适合您的情况。
弗拉基米尔·霍里科夫(Vladimir Khorikov)撰写了一篇很棒的简单文章: 规范模式:C#实现
他发表在GitHub上的示例项目在这里
如果链接无效,我在这里添加主要的核心逻辑。
您的存储库将如下所示:
public IReadOnlyList<T> Find(Specification<T> specification)
{
using (context))
{
return context.DbSet<T>()
.Where(specification.ToExpression())
.ToList();
}
}
对于Specification类,您可以找到许多实现。
它是一个小的实用程序类,最终将其转换为表达式
如果您这样设计应用程序,则可以轻松测试您的规范(实际上是您的表达方式)
我不确定测试表达式是否是个好主意。 但是,如果您愿意,可以尝试。 对于这种要求,我至少有一个主意。
将需要提供一个模拟而不是您的存储库,您可以使用任何所需的库。 Moq或NSubstitute作为示例。
然后,应该在Expression<Func<Domain.Person, bool>>
对象传递到SingleOrDefaultAsync
调用中的存储库中。 对于大多数模拟库来说,这应该非常简单。
最后,您需要将表达式编译成Func<Domain.Person, bool>
并断言对于具有预期Id
Domain.Person
对象它返回true
,否则返回false
。
还有一个小的快照来说明,我在这里假设只有一个参数,只有对存储库对象的调用,并且Domain.Person.Id
具有公共设置器。
var repository = Substitute.For<IRepository>();
var service = new Service(repository);
var person = new Domain.Person { Id = 42 };
await service.ArchiveAsync(person);
var call = repository.ReceivedCalls().First();
var arg = call.GetArguments().First();
var expr = (Expression<Func<Domain.Person, bool>>)arg;
var func = expr.Compile();
Assert.True(func(person));
Assert.False(func(new Domain.Person {Id = 1}));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.