是否应该测试/模拟包含 LINQ 表达式的方法?
假设我有一个类,其方法采用 System.Linq.Expressions.Expression 作为参数,那么单元测试有多少价值?
public void IList<T> Find(Expression expression)
{
return someCollection.Where(expression).ToList();
}
单元测试或模拟这些方法对我来说是一种令人煎熬的经历,我现在不得不怀疑这一切是否不值得。
我如何使用一些任意表达式来单元测试这个方法,例如
List<Animal> = myAnimalRepository.Find(x => x.Species == "Cat");
Assuming I have a class with a method that takes a System.Linq.Expressions.Expression as a parameter, how much value is there in unit testing it?
public void IList<T> Find(Expression expression)
{
return someCollection.Where(expression).ToList();
}
Unit testing or mocking these sorts of methods has been a mind-frying experience for me and I'm now at the point where I have to wonder whether it's all just not worth it.
How would I unit test this method using some arbitrary expression like
List<Animal> = myAnimalRepository.Find(x => x.Species == "Cat");
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
对此进行单元测试有点人为,因为每个 LINQ 提供程序都是特定于实现的。您可能在测试中使用各种不同的方法,但它根本不会告诉您有关实际实现的任何信息。例如,如果通过 LINQ-to-Objects 模拟它,我可以使用:
这将与 LINQ-to-Objects 一起使用...但仅与 LINQ-to-Objects 一起使用。同样,UDF 用法(或 SQL 帮助器方法之一)将在 LINQ-to-SQL 中工作,但不能在实体框架中工作。
我得出的结论是,只有集成测试对这种情况有用,所以不行;嘲笑在这里不是很有帮助。它会给你一种温暖而快乐的感觉,因为你做了一些有用的事情,但最终它并不能测试你在应用程序中编写的内容是否有效。
在我看来,更好的方法是不要通过存储库接口公开此类内容。如果将 LINQ 查询限制在数据层,则可以消除风险,现在您正在测试(/模拟)一个纯粹的、可预测的接口。
我更多内容在这里讨论。
It is a bit artificial to unit test this, since each LINQ provider is implementation-specific. You might use various different approaches in your test, and it simply won't tell you anything about the real implementation. For example, if it is mocked via LINQ-to-Objects, I could use:
That will work with LINQ-to-Objects... but only with LINQ-to-Objects. Likewise, a UDF usage (or one of the SQL helper methods) will work in LINQ-to-SQL but not Entity Framework.
I've reached the conclusion that only integration tests are useful for this scenario, so no; mocking isn't very helpful here. It will give you a warm happy feeling that you've done something useful, but ultimately it doesn't test that what you write in your app will work.
An even better approach, IMO, is not to expose such over your repository interface. If you limit the LINQ queries to your data-layer you remove the risk and now you are testing (/mocking) a pure, predicatable interface.
I discuss this more here.
为什么不呢? -
它是 SUT 公共接口的一部分。
这看起来也很容易测试。除非绝对需要,否则我通常不会使用模拟。我会编写类似 Arrange: setup SUT 的测试
Assert.That( results.Is.EquivalentTo(expected_results)
您可以尝试几个查询表达式以确保 Find 方法将其用作一个Where子句就可以了。
Why not? -
It is part of the public interface of the SUT.
This looks easy to test as well. I generally don;t use mocks unless its absolutely required. I'd write the test like
Assert.That( results.Is.EquivalentTo(expected_results)
You can try a couple of query expressions to ensure that the Find method is using it as a Where clause. That should do it.