是否应该测试/模拟包含 LINQ 表达式的方法?

发布于 2024-08-29 18:26:59 字数 397 浏览 11 评论 0原文

假设我有一个类,其方法采用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我的黑色迷你裙 2024-09-05 18:26:59

对此进行单元测试有点人为,因为每个 LINQ 提供程序都是特定于实现的。您可能在测试中使用各种不同的方法,但它根本不会告诉您有关实际实现的任何信息。例如,如果通过 LINQ-to-Objects 模拟它,我可以使用:

List<Animal> = myAnimalRepository.Find(x => CheckSpecies(x, "Cat"));
...
static bool CheckSpecies(Animal animal, string species) {
    return animal.Species == species;
}

这将与 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:

List<Animal> = myAnimalRepository.Find(x => CheckSpecies(x, "Cat"));
...
static bool CheckSpecies(Animal animal, string species) {
    return animal.Species == species;
}

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.

淡淡離愁欲言轉身 2024-09-05 18:26:59

为什么不呢? -
它是 SUT 公共接口的一部分。

这看起来也很容易测试。除非绝对需要,否则我通常不会使用模拟。我会编写类似 Arrange: setup SUT 的测试

[Test]
public void Find()
{
  var animalRepository = new AnimalRepository();
  animalRepository.Add( dog ); // create a object to species = dog and other relevant attr
  animalRespository.Add( cat ); // etc. etc..

  var results = animalRepository.Find( a => a.Species == "Cat");

  Assert.That( results.Is.EquivalentTo( new List<Animal> { cat } ) );
}
  1. ,以便内部 somecollection 包含一些已知对象 - 例如 Add(dog);添加(猫);行动
  2. :使用条件调用 Find 方法
  3. Assert: 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

[Test]
public void Find()
{
  var animalRepository = new AnimalRepository();
  animalRepository.Add( dog ); // create a object to species = dog and other relevant attr
  animalRespository.Add( cat ); // etc. etc..

  var results = animalRepository.Find( a => a.Species == "Cat");

  Assert.That( results.Is.EquivalentTo( new List<Animal> { cat } ) );
}
  1. Arrange: setup SUT so that internal somecollection contains a few known objects - e.g. Add(dog); Add(cat); etc.
  2. Act: invoke the Find method with a condition
  3. Assert: 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文