我正试图在测试中断言2 Linq表达式。我正在使用Moq并在回调时捕获在被测试方法中调用的表达式。
Expression<Func<Role, bool>> actualExpression = null;
roleRepositoryMock.Setup(t => t.Search(It.IsAny<Expression<Func<Role, bool>>>()))
.Callback((Expression<Func<Role, bool>> exp) =>
{
actualExpression = exp;
})
.Returns(new List<Role> { new Role { Name = "site1_code_role1", Description = "descr" }, new Role { Name = "site1_code" } });
然后我将对此进行比较:
var siteCode = "site1";
var namePattern = "role1";
Expression<Func<Role, bool>> expectedExpression =
t => (string.IsNullOrEmpty(siteCode)
|| t.Name.StartsWith(siteCode + "_")
|| t.Name == siteCode)
&& t.Name.Contains(namePattern);
Assert.AreEqual(expectedExpression.ToString(), actualExpression.ToString());
以上断言失败。字符串的预期表达式等于:
t => (((IsNullOrEmpty(value(BL.Tests.RolesServiceTests+<>c__DisplayClass6).siteCode) OrElse t.Name.StartsWith((value(BL.Tests.RolesServiceTests+<>c__DisplayClass6).siteCode + "_"))) OrElse (t.Name == value(BL.Tests.RolesServiceTests+<>c__DisplayClass6).siteCode)) AndAlso t.Name.Contains(value(BL.Tests.RolesServiceTests+<>c__DisplayClass6).namePattern))
实际表达式等于:
t => (((IsNullOrEmpty(value(BL.Services.RolesService+<>c__DisplayClass3).site) OrElse t.Name.StartsWith((value(BL.Services.RolesService+<>c__DisplayClass3).site + "_"))) OrElse (t.Name == value(BL.Services.RolesService+<>c__DisplayClass3).site)) AndAlso t.Name.Contains(value(BL.Services.RolesService+<>c__DisplayClass3).pattern))
差异在于:
任何人都可以解释或向我发送正确的方向,说明为什么以及如何解决它? 也许通过ToString()尝试比较这些是绝对错误的方法?替代?
答案 0 :(得分:0)
最好编写一些测试来验证一段代码的外部可观察行为,而不需要与实现细节相结合。通过将表达式转换为字符串,您不仅可以将测试与您的确切表达式相结合,还可以将ToString
方法的实现结合起来,这可能会在将来的.NET版本中发生变化。
更好的方法是在某些输出状态上断言。看起来您要验证传递到存储库的linq表达式是否会过滤掉正确的Role
集合。由于您已经可以通过回调捕获表达式,为什么不针对此表达式编写一些测试?
假设Role
是POCO,编写使用Role
输入的不同集合调用表达式的测试并断言产生正确的输出应该是微不足道的。如果表达式很复杂,您可能需要很多输入,但它看起来像这样:
var roles = new List<Role>
{
new Role { Name = siteCode+"_role1" },
new Role { Name = siteCode+"_role22" },
new Role { Name = siteCode+"_role1324" },
};
Assert.AreEqual(2, roles.Where(actualExpression.Compile()).Count()); //test the number of roles returned is as expected
更好的做法是仅在客户端代码的接口上进行测试,而不需要测试任何有关如何查询存储库的知识。