Should I test / mock methods containing LINQ expressions?

Assuming I have a class with a method that takes a System.Linq.Expressions.Expression parameter as a parameter, how much is the value in unit testing?

public void IList<T> Find(Expression expression) { return someCollection.Where(expression).ToList(); } 

Unit testing or mockery of such methods was an impressive experience for me, and now I am at a point where I have to wonder if all this is simply not worth it.

How would I unit test this method used some kind of arbitrary expression like

 List<Animal> = myAnimalRepository.Find(x => x.Species == "Cat"); 
+4
source share
2 answers

This is a little artificial for a unit test, since each LINQ provider is implementation specific. In your test, you can use various approaches, and it just will not tell you anything about the real implementation. For example, if he mocks through LINQ-to-Objects, I can use:

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

This will work with LINQ-to-Objects ... but only with LINQ-to-Objects. Similarly, using UDF (or one of the SQL helper methods) will work in LINQ-to-SQL, but not in the Entity Framework.

I came to the conclusion that only integration tests are useful for this scenario, so no; mockery is not very useful. This will give you a warm, happy feeling that you have done something useful, but in the end it does not verify that what you write in your application will work.

An even better approach, IMO, is not to expose such an interface through your repository interface. If you limit LINQ queries to your data layer, you eliminate the risk, and now you are testing (/ mocking) a clean, predicate interface.

I discuss this one here .

+6
source

Why not? - This is part of the open SUT interface.

This is easy to verify. I donโ€™t use mocks at all unless this is required. I would write a test, for example

 [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 } ) ); } 
  • Arrange: configure SUT so that the internal somecollection contains several known objects - for example. Add (dog); Add (cat); and etc.
  • Act: call the Find method with the condition
  • Statement: Assert.That( results.Is.EquivalentTo(expected_results)

You can try a couple of query expressions to make sure the Find method uses it as a Where clause. That should do it.

+2
source

Source: https://habr.com/ru/post/1307615/


All Articles