3

I am having a problem with unit testing in c#. They don't give back correct one although they should.

this is the code of the method called in the test unit method

public static List<Examen> filterExamensCities(List<Examen> original, List<string> steden)
{
    List<Examen> result = new List<Examen>();

    foreach (Examen ex in original)
    {
        foreach (string stad in steden)
        {
            if (ex.Locatie == stad)
            {
                result.Add(ex);
            }
        }
    }
    return result;
}

This is the code of the test unit method

[TestMethod]
public void filterExamensCities()
{
    //Creatie test data
    List<Examen> origineleLijst = new List<Examen>();
    origineleLijst.Add(new Examen(DateTime.Today, 2, 2, true, "Bouwmeesterstraat", 1));
    origineleLijst.Add(new Examen(DateTime.Today, 2, 3, true, "Schilderstraat", 2));
    origineleLijst.Add(new Examen(DateTime.Today, 2, 3, true, "Meistraat", 3));

    List<string> stedenLijst = new List<string>();
    stedenLijst.Add("Meistraat");

    List<Examen> verwachteLijst = new List<Examen>();
    verwachteLijst.Add(new Examen(DateTime.Today, 2, 3, true, "Meistraat", 3));

    //methode oproepen en assert
    List<Examen> resultLijst = FilterModel.filterExamensCities(origineleLijst, stedenLijst);

    Assert.AreEqual(verwachteLijst, resultLijst, "Fout");
}

I am using the build in tests from visual studio.

jessehouwing
  • 106,458
  • 22
  • 256
  • 341
Robin
  • 2,704
  • 7
  • 30
  • 47
  • 1
    Without knowing which unit test library you're using this is quite tricky but my suspicion is that you're comparing the two lists for equality (probably reference equality) rather than the values of the entities within. – Liath Dec 13 '13 at 11:55
  • You named that method `filterExamensFullCapacity` which seems to mean you want all full exams. However you select only the exams that have positions left – Hans Kesting Dec 13 '13 at 11:55
  • 2
    Looks a lot like Mstest to me :). The `[TestMethod]` gives it away. – jessehouwing Dec 13 '13 at 12:16

4 Answers4

3

You should use CollectionAssert.AreEqual method if you are comparing collections:

CollectionAssert.AreEqual(verwachteLijst, resultLijst);

If the item type in the collection does not implement equality, you can provide a custom comparer by implementing IComparer interface.

CollectionAssert.AreEqual(verwachteLijst, resultLijst, new CustomComparer());
Ufuk Hacıoğulları
  • 37,978
  • 12
  • 114
  • 156
2

Assert.AreEqual checks whether the two collection instances are the same collection. They don't look at the contents of the collection in this case.

Instead use CollectionAssert.AreEquivalent. This will probably only work when Examen overrides Equals and GetHashCode. Alternatively write your test case to re-use the examen instances, in which case you can use CollectionAssert.AreEqual

To write your test to re-use instances of Examen:

[TestMethod]
public void filterExamensCities()
{
    examenDatum = DateTime.Today;
    Examen eersteExamen = new Examen(examenDatum, 2, 2, true, "Bouwmeesterstraat", 1);
    Examen tweedeExamen = new Examen(examenDatum, 2, 3, true, "Schilderstraat", 2);
    Examen derdeExamen = new Examen(examenDatum, 2, 3, true, "Meistraat", 3);

    //Creatie test data
    List<Examen> origineleLijst = new List<Examen>();
    origineleLijst.Add(eersteExamen);
    origineleLijst.Add(tweedeExamen);
    origineleLijst.Add(derdeExamen);

    List<string> lokatieLijst = new List<string>();
    lokatieLijst.Add("Meistraat");

    List<Examen> verwachteLijst = new List<Examen>();
    verwachteLijst.Add(derdeExamen);

    //methode oproepen en assert
    List<Examen> resultLijst = FilterModel.filterExamensCities(origineleLijst, lokatieLijst);

    //use one of these depending on whether Examen implements Equals and GetHashcode properly.       
    CollectionAssert.AreEqual(verwachteLijst, resultLijst, "Fout");
    CollectionAssert.AreEquivalent(verwachteLijst, resultLijst, "Fout");
}

Examen should implement Equals and GetHashCode if you want to be able to compare on contents instead of instance

See:

You might as well rewrite your code under test as:

public static List<Examen> FilterExamensOpLokatie(List<Examen> examensOmTeFilteren, List<string> gewensteLokaties)
{
    return examensOmTeFilteren.Where(examen => gewensteLokaties.Contains(examen.Locatie)).ToList();
}
Community
  • 1
  • 1
jessehouwing
  • 106,458
  • 22
  • 256
  • 341
1

you should use Enumerable.SequenceEqual to compare the lists

try this:

Assert.IsTrue(Enumerable.SequenceEqual(verwachteLijst, resultLijst));

This will requir that your Examen can determin if it is equal to other instances of the Examen class

Jens Kloster
  • 11,099
  • 5
  • 40
  • 54
0

Think carefully about what Assert.AreEqual does. It checks whether two objects are equal. They are not equal because they are two different objects.

Suppose you do the following:

var a = new Object();
var b = new Object();
Assert.AreEqual(a, b);

Objects a and b are not the same object! In your case, you would have to check whether the two lists have the same length and if this is the case, check whether each object in one list is equal to an object in the other list.

Of course, when comparing the Examen objects in your lists, take this into account as well! Two different Examen instances that happen to have the same property values are not equal. Since these are your own classes, you can either:

EDIT: An easier way to compare two lists is suggested by Jens Kloster (Enumerable.SequenceEqual).

** Check here if you want to know why you should override bot Equals and GetHashCode.

Community
  • 1
  • 1
Ronald Wildenberg
  • 31,634
  • 14
  • 90
  • 133
  • I was affraid that this would be the issue, but does this mean I have to run a foreach in the assert? – Robin Dec 13 '13 at 12:00