在ToString的帮助下比较c#中的lambda表达式
本文关键字:中的 lambda 表达式 比较 ToString 帮助 | 更新日期: 2023-09-27 18:07:28
我试图在测试中断言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());
上面的Assert失败。期望的字符串表达式等于:
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))
差异在于:
- c_DisplayClass6和c_DisplayClass3
- BL.Services。RolesService和BL.Tests.RolesServiceTests(命名空间不同)
谁能解释或给我正确的方向为什么和如何解决它?也许这是一个绝对错误的方式来尝试和比较这些通过ToString()?选择呢?
最好编写测试来验证一段代码的外部可观察行为,而不耦合到实现细节。通过将表达式转换为字符串,您不仅将测试与您的精确表达式耦合,而且还将测试与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
更好的方法是只在客户端代码的接口上进行测试,而不让测试知道如何查询存储库。