给出以下示例代码:
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
没有返回正确的结果是否正确?我假设是这样的,因为根据ICriteria<Person>
的值生成单独的searchType
对象生成三元组正在产生正确的结果。但是我不确定这是因为L2S无法将三元转换为商店表达式,或者是否由其他原因引起。
由于测试中的方法取决于IRepository<Person>
实例,我怎样才能真正围绕此实例编写单元测试?在单元测试中模拟IRepository<Person>
将不允许我们测试lambda对真实底层数据的影响。创建由某种FakePersonRepository
支持的IList<Person>
不会显示实际缺陷,因为上面带有三元表达式的lambda使用linq-to-objects返回预期结果。有没有什么方法可以模拟L2S的一部分,以便我们可以使用lambda生成SQL,然后针对它编写断言?
这只是我们与集成测试和带有连接字符串的实际L2S上下文有关,而不能正确进行单元测试吗?我对“集成测试”的定义意味着“使用某种连接字符串连接到与测试运行器分开运行的实际数据库”,而“单元测试”意味着“在测试运行程序中执行所有操作”。
答案 0 :(得分:1)
- L2S(...)没有返回正确的结果是否正确
醇>
它确实会返回正确的结果,但不会返回您期望的结果,因为您将查询视为人而不是编译器。后者读到了这个:
tableToQuery.Where(p =>
((p.IsMale == false) && type.Equals("User", StringComparison.OrdinalIgnoreCase))
? p.User != null
: p.User == null);
我们人类倾向于阅读这个:
tableToQuery.Where(p => (p.IsMale == false) &&
(type.Equals("User", StringComparison.OrdinalIgnoreCase)
? p.User != null
: p.User == null));
2./3。我怎么能真正围绕这个进行单元测试?
模拟和单元测试几乎是不可能的。当我想测试数据层的行为时,我坚持使用集成测试。对于实体框架,我收集了集成测试here的一些原因。其中大部分也适用于LINQ-to-SQL。