繁体   English   中英

如何对传递到存储库层的表达式进行单元测试

[英]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类,您可以找到许多实现。
它是一个小的实用程序类,最终将其转换为表达式

如果您这样设计应用程序,则可以轻松测试您的规范(实际上是您的表达方式)

我不确定测试表达式是否是个好主意。 但是,如果您愿意,可以尝试。 对于这种要求,我至少有一个主意。

将需要提供一个模拟而不是您的存储库,您可以使用任何所需的库。 MoqNSubstitute作为示例。

然后,应该在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM