【发布时间】:2015-03-25 19:59:06
【问题描述】:
给出以下示例代码:
Table<Person> tableToQuery = MethodThatGetsReferenceToPersonTable();
string searchType = "NonUser";
IQueryable<Person> queryResults = tableToQuery.Where(p =>
(p.IsMale == false) && // exclude male people
type.Equals("User", StringComparison.OrdinalIgnoreCase)
? p.User != null : p.User == null);
我是 L2S 新手,但对 EntityFramework 有一些经验。我不希望上述查询在像 EF 这样的 ORM 中正常工作,因为在谓词的三元表达式中调用了 type.Equals。相反,我希望 EF 抛出异常,因为它无法将谓词的那部分转换为 (SQL) 存储表达式。
使用 L2S,.Where 似乎正在返回数据,但不排除 p.Male == true 时 type == "NonUser 的项目。我已经修复了上面的代码以将type.Equals 三元组从谓词中提取出来并返回正确的结果,现在我正在尝试编写一个测试来断言正确的结果。我遇到的问题是 L2S 代码实际上位于 IRepository<Person> 接口后面。
所以实际代码看起来更像这样:
string searchType = "NonUser";
ICriteria<Person> query = new Query<Person>(p =>
(p.IsMale == false) && // exclude male people
type.Equals("User", StringComparison.OrdinalIgnoreCase)
? p.User != null : p.User == null);
IQueryable<Person> = _peopleRepository.FindByQuery(query)
...而_peopleRepository 实现只是将query.Predicate 作为参数传递给L2S Table<Person>.Where。
问题:
由于 lambda 谓词中的三元表达式,L2S
Table<Person>.Where未返回正确结果是否正确?我假设是这样,因为根据searchType的值将三元组取出生成单独的ICriteria<Person>对象会产生正确的结果。但是我不太确定这是因为 L2S 无法将三元转换为存储表达式,还是由其他原因引起的。由于被测方法依赖于
IRepository<Person>实例,我如何才能真正围绕它编写单元测试?在单元测试中模拟IRepository<Person>不允许我们测试 lambda 对真实基础数据的影响。创建由某种IList<Person>支持的FakePersonRepository也不会揭示实际缺陷,因为上面带有三元表达式的 lambda 使用 linq-to-objects 返回预期结果。有什么方法可以模拟 L2S 的一部分,以便我们可以使用 lambda 生成 SQL,并针对它编写断言?这只是我们必须与集成测试和带有连接字符串的实际 L2S 上下文相关的事情,并且无法正确进行单元测试吗?我对“集成测试”的定义是指“使用某种连接字符串连接到在与测试运行程序不同的进程中运行的实际数据库”,而“单元测试”是指“在测试运行程序进程中执行所有操作”。
【问题讨论】:
-
这也是我从不测试或模拟“原始”LINQ,而只测试或模拟返回结果的组件的原因之一 - 组件本身在 real 数据库的上下文中进行测试(并且仅在它们依赖于正在测试的其他组件时才被模拟)。
-
@user2864740 那么你对问题 #3 说“是”吗?
-
我相信围绕 L2E/L2S 查询的单元测试从根本上涉及数据库作为“单元”的一部分(并且该单元包含在公开使用权)。在处理事务和横切上下文等时,事情变得更加不确定 - 而这些肯定会推动“单元”信封。但是单元测试不能模拟它正在尝试测试的内容 .. 否则它最终什么都不测试。
-
也就是说,我相信 L2E/L2S 查询是单元测试,基本上是单元测试原始数据库访问本身,隐藏在强类型查询语法之后。跨度>
-
@user2864740 我明白你在说什么,但是当测试需要连接到一个实际的数据库时——无论是 SQL、LocalDb 还是其他的——它从单元测试到我定义的集成测试。使用我的定义来区分
unit和integration,您是否对问题#3 回答“是”?
标签: unit-testing linq-to-sql lambda predicate