3

I asked a question on here earlier and Laiv shared the following link.

In the article; it is stated that Eric Evans avoids .equals methods on Entities.

In this question; the accepted answerer talks about using Custom Assertions for Unit Testing rather than .equals

Therefore I am looking at custom assertions. I have created the following class, which compares two products:

public static bool IsSameDescription(Product product1, Product product2)
        {
            // Check for null values and compare run-time types.
            if (product1 == null || product2==null)
                return false;

            return (product1.description == product2.description);
        }

Therefore I can do this in the Unit Test:

Assert.AreEqual(expectedProduct, actualProduct);

What is I wanted to compare two lists of products? I could use a .equals method and then do this:

CollectionAssert.AreEqual(expectedProductList, actualProductList);

How would I implement this? I could implement a static function that accepts two lists and compares them. However, CollectionAssert would not use it? Would it? (because it uses .equals behind the scenes) How can I do this?

  • 1
    Doesn't the API has something like Assert.isTrue()? For instance Assert.isTrue(IsSameDescription(productA, productB)) – Laiv Aug 17 '17 at 14:04
  • On the other hand, correct me if I'm worng, looks like you are only concerned about equality because the Unit testing. This's what my link would catalog as intention and that's why your link advocates for custom assertions. How to implement custom assertions is implementation details. You should look at the Assert API and do use of all its possibilities. – Laiv Aug 17 '17 at 14:15
6

To apply the same method to a collection, you can use LINQ to great effect.

If you want to compare everything to the same instance you can do this:

productList.Select(item => IsSameDescription(productA, item)).ToList();

The CollectionAssert also has a variant that takes a comparator function:

CollectionAssert(expectedProductList, actualProductList, IsSameDescription);

Clarification about custom exceptions:

The primary reason to use custom assertions rather than the generic AssertTrue or Assert.IsTrue is that the error messages provide more detail as to what exactly the problem was. For example, Assert.AreEqual(obj1, obj2) or Assert.That(obj1).IsEqualTo(obj2) will tell you both what the expected answer was and what the actual value was. That should be the goal you are looking for with any custom assertion.

There are several assertion libraries, so you might have to re-invent the wheel. Some test libraries have the assertion library included (Like NUnit, JUnit, etc.).

I would much rather see intelligent use of a standard assertion library than writing custom assertions for everything. Using the example you provided:

Assert.AreEqual(product1.Description, product2.Description);

Is as expressive as you need.

  • What is myCollection? What is product? What is Item? Sorry I don't really understand this. – w0051977 Aug 17 '17 at 15:25
  • I'm using the variable names you defined. I changed myCollection to your example. item is the iterated entry alias. Read up on LINQ and lambda expressions for more information. – Berin Loritsch Aug 17 '17 at 15:49
  • Be careful with the linq implementation. You have to be sure to actually materialize the query or you'll get wonky results. CollectionAssert with the comparator is much more reliable. – RubberDuck Aug 17 '17 at 23:54
  • Correct. If you call ToList() after the select statement to force the LINQ to iterate over the contents it will do it's job. I'll modify the answer to include that. Do note that the two statements are testing different things. The LINQ statement is testing all elements of a collection to a constant product. The CollectionAssert with comparator option is testing two collections against each other. – Berin Loritsch Aug 18 '17 at 13:46
0

As alternative FluentAssertions library have nice bunch of assertion methods and possibility to configure them in readable manner.

In your particular case ShouldAllBeEquivalentTo method can be used

var expectedProducts = new[]
{
    new Product { Id = 1, Description = "One" },
    new Product { Id = 2, Description = "Two" }
}

var actualProducts = classUnderTest.CreateProducts();

actualProducts.ShouldAllBeEquivalent(
     expectedProducts, 
     config => config.Including(product => product.Description));

ShouldAllBeEquivalent will assert that actual collection contains same products as expected collection, where equality will be asserted by only Description property.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.