CSharpFeeds - All your C# feeds in one place.

Sponsors

Monday, October 01, 2007

Unit Testing Generic Lists

by Keyvan Nayyeri via Keyvan Nayyeri on 10/1/2007 1:58:00 AM

If you do unit tests frequently, know that unit testing a generic list is a very common scenario because generic lists are a common part of today's codes in the .NET world.

Testing the equality of two generic lists isn't as easy as easy testing the equality of two objects from two simple types.  In order to test two generic lists, you need to follow one of two approaches that I describe in this post.  One of them is easy and can be done quickly and the second one may need more effort.

Background

First suppose that you have a Person class like this:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace GenericList

{

    public class Person

    {

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public int Age { get; set; }

        public string Sex { get; set; }

 

        public Person()

        {

        }

 

        public Person(string firstName, string lastName, int age, string sex)

        {

            this.FirstName = firstName;

            this.LastName = lastName;

            this.Age = age;

            this.Sex = sex;

        }

    }

}

And also suppose that you have another class named PersonCollection derived from generic list of Person.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace GenericList

{

    public class PersonCollection : List<Person>

    {

        public Person GetOldest()

        {

            int maxAge = 0;

            Person chosenPerson = new Person();

 

            foreach (Person person in this)

            {

                if (person.Age > maxAge)

                {

                    maxAge = person.Age;

                    chosenPerson = person;

                }

            }

 

            return chosenPerson;

        }

    }

}

Now I write a People class that doesn't have anything but a List property of PersonCollection type.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace GenericList

{

    public class People

    {

        public PersonCollection List { get; set; }

    }

}

Override Equals Method

The first approach, and the approach that I personally would prefer to the second one, is overriding the Equals method for the generic list class in your code.  In this case, when you call Assert.AreEqual to check the equality of two lists of this type, then it can compare two lists in the right way that you teach to it.

In the above example, I can update the PersonCollection class to override the Equals method.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace GenericList

{

    public class PersonCollection : List<Person>

    {

        public Person GetOldest()

        {

            int maxAge = 0;

            Person chosenPerson = new Person();

 

            foreach (Person person in this)

            {

                if (person.Age > maxAge)

                {

                    maxAge = person.Age;

                    chosenPerson = person;

                }

            }

 

            return chosenPerson;

        }

 

        public override bool Equals(object obj)

        {

            PersonCollection input = obj as PersonCollection;

 

            if (input.Count != this.Count)

                return false;

 

            for (int index = 0; index < input.Count; index++)

            {

                Person inputPerson = input[index];

                Person originalPerson = this[index];

 

                if ((inputPerson.FirstName != originalPerson.FirstName) ||

                    (inputPerson.LastName != originalPerson.LastName) ||

                    (inputPerson.Age != originalPerson.Age) ||

                    (inputPerson.Sex != originalPerson.Sex))

                    return false;

            }

            return true;

        }

 

        public override int GetHashCode()

        {

            return base.GetHashCode();

        }

    }

}

Now I can write a test method to test the List property of People class.

/// <summary>

///A test for List

///</summary>

[TestMethod()]

public void ListTest()

{

    People target = new People();

    PersonCollection expected = new PersonCollection();

    expected.Add(new Person("Keyvan", "Nayyeri", 23, "Male"));

    expected.Add(new Person("Mehrdad", "Ebrahimi", 24, "Male"));

 

    PersonCollection actual = new PersonCollection();

    target.List = expected;

    actual = target.List;

    Assert.AreEqual(expected, actual);

}

For two reasons this may be hard or impossible for you:

  • You can't change the original code when writing your test methods.
  • The original type (Person in the above example) may be complicated and consists of several properties that make it harder to write codes for it.

Despite these two negative points, this approach is better because:

  • By overriding the Equals method you make your codes better and this is very good especially if you're writing a library or framework.
  • You may need this Equals method for other purposes and here one time forever you've done it!

Write a Generic Test Method

The second approach is easier to achieve but works as just a testing solution and can't provide abovementioned benefits for you.

You can simply write a generic test method that gets two generic lists and tests them on fly.

/// <summary>

///A test for List

///</summary>

[TestMethod()]

public void ListTest()

{

    People target = new People();

    PersonCollection expected = new PersonCollection();

    expected.Add(new Person("Keyvan", "Nayyeri", 23, "Male"));

    expected.Add(new Person("Mehrdad", "Ebrahimi", 24, "Male"));

 

    PersonCollection actual = new PersonCollection();

    target.List = expected;

    actual = target.List;

 

    GenericTest<Person>(expected, actual);

}

 

private void GenericTest<T>(List<T> actual, List<T> expected)

{

    IEnumerator<T> actualEnumerator = actual.GetEnumerator();

 

    for (int i = 0; i < expected.Count; i++)

    {

        Assert.IsTrue(actualEnumerator.MoveNext());

        Assert.IsTrue(actualEnumerator.Current.Equals(expected[i]));

    }

 

    Assert.IsFalse(actualEnumerator.MoveNext());

}

This is a quick way and I use it when want to test codes faster!

Test Results

email it!bookmark it!digg it!

Original Post: Unit Testing Generic Lists

Legal Note

The content of the postings is owned by the respective author. CSharpFeeds is not responsible for the contents of the postings. This site is automatically generated and cannot be reviewed for abusive content. If you find abusive content on CSharpFeeds, please contact us. Designated trademarks and brands are the property of their respective owners. All rights reserved.

Advertise with us