MSTest CollectionAssert class - an overview
Published: 2020-03-14 14:08:54

---
title: MSTest CollectionAssert class - an overview
published: true
description: The CollectionAssert class if fine for basic tests on collections in C#. We will have a look at the methods exposed by this class.
tags: 
canonical_url: https://www.code4it.dev/blog/mstests-collectionassert-overview
cover_image: https://res.cloudinary.com/bellons/image/upload/t_dev-to/Code4IT/Covers/unit-testing-collectionassert.jpg
---

This is the third part of our journey. In the [first part](https://www.code4it.dev/blog/mstests-assert-overview) we listed the methods belonging to the __Assert__ class, while in the [second part](https://www.code4it.dev/blog/mstests-stringassert-overview) we had a look at the __StringAssert__ class. 

Now we'll deep dive into the CollectionAssert class, which is a good fit for ensuring that a collection of elements follows desired specifications.

## Introduction to CollectionAssert

[This class](https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.testtools.unittesting.collectionassert) tests various conditions associated with collections, like tests about the type of the elements. It is important to say that this class does not check if every element in the collection follows a certain rule (like "The ID must be greater than 0"), but it's more about __high level checks__.


For these examples I'll reuse two classes created for the first article of this series: _User_ and _AdminUser_: the second class extends the first one:

```csharp
public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
}
 
public class AdminUser : User
{
    public string Department { get; set; }
}

```

## CollectionAssert.AllItemsAreInstancesOfType
With this method we can check if all the elements belonging to a collection are of the same type. 

A simple example could be the one with a list of strings.

``` csharp
[TestMethod]
public void AllItemsAreInstanceOfType_String()
{
    string[] stringArray = new string[] { "Hello", "darkness", "my", "old", "friend" };

    CollectionAssert.AllItemsAreInstancesOfType(stringArray, typeof(string));
}
``` 

Of course all the elements in the `stringArray` array are all strings, so it's easy to guess that the test will pass. 

What about objects? In the next test I'll create a List of `User` elements, but with also an `AdminUser` object.
You should remember that AdminUser is also a User, but the vice versa is not true.

``` csharp
[TestMethod]
public void AllItemsAreInstanceOfType_AreAllUsers()
{
    List<User> list = new List<User>()
    {
        new User(){ Username = "Elvis", Id=1},
        new User(){ Username="Janis", Id=2},
        new AdminUser(){ Username="Freddie", Id=3, Department="Legends"}
    };

    CollectionAssert.AllItemsAreInstancesOfType(list, typeof(User)); //Pass
    CollectionAssert.AllItemsAreInstancesOfType(list, typeof(AdminUser)); //Fail
}
```

The first test will pass, but the second one will fail because the object with Username = "Freddie" is the only object of type `AdminUser`.


## CollectionAssert.AllItemsAreNotNull
This method is pretty straightforward: if an element in the collection is `null` it will fail.

```csharp
[TestMethod]
public void AllItemsAreNotNull()
{
    List<User> list = new List<User>() {
        new User(){Username= "Elvis", Id=1},
        null,
        new AdminUser(){ Username="Freddie", Id=3, Department="Legends"}
    };

    CollectionAssert.AllItemsAreNotNull(list);
}

```

Of course the test above will fail.

## CollectionAssert.AllItemsAreUnique
The name is explicative.

The test below will pass:
```csharp
[TestMethod]
public void AreAllItemsUnique_integers()
{
    int[] array = new int[] { 1, 2, 3, 9, 7 };
    CollectionAssert.AllItemsAreUnique(array);
}
```

But life is not meant to be lived with only integers.
And that's where things become a bit harder.

```csharp
[TestMethod]
public void AreAllItemsUnique_Users()
{
    User[] array = new User[] {
        new User(){Username= "Elvis", Id=1},
        new User(){Username= "Elvis", Id=1}
    };
    CollectionAssert.AllItemsAreUnique(array);
}
```

Well, Elvis will be unique forever... but not here! The `array` variable contains two different instances of `User`, even if the properties have the same value. So this test will fail.

Digging a bit more into the `AllItemsAreUnique` class we can see that internally it works with dictionaries:

```csharp
public static void AllItemsAreUnique(ICollection collection, string message, params object[] parameters)
{
	Assert.CheckParameterNotNull(collection, "CollectionAssert.AllItemsAreUnique", "collection", string.Empty);
	message = Assert.ReplaceNulls(message);
	bool flag = false;
	Dictionary<object, bool> dictionary = new Dictionary<object, bool>();
	foreach (object item in collection)
	{
		if (item == null)
		{
			if (!flag)
			{
				flag = true;
			}
			else
			{
				string message2 = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.AllItemsAreUniqueFailMsg, new object[2]
				{
					(message == null) ? string.Empty : message,
					FrameworkMessages.Common_NullInMessages
				});
				Assert.HandleFail("CollectionAssert.AllItemsAreUnique", message2, parameters);
			}
		}
		else if (dictionary.ContainsKey(item))
		{
			string message3 = string.Format(CultureInfo.CurrentCulture, FrameworkMessages.AllItemsAreUniqueFailMsg, new object[2]
			{
				(message == null) ? string.Empty : message,
				Assert.ReplaceNulls(item)
			});
			Assert.HandleFail("CollectionAssert.AllItemsAreUnique", message3, parameters);
		}
		else
		{
			dictionary.Add(item, value: true);
		}
	}
}
```

Ok, it's not so exciting, but I wanted to show you what's under the hood and how comparison is handled.

So, let's get back to our problem: how can we make that test pass?

We must override the `Equals` and the `GetHashCode` method. Even here I reuse the `UpdatedUser` class from the first article 

```csharp
public class UpdatedUser
{
    public int Id { get; set; }
    public string Username { get; set; }
    public override bool Equals(object obj)
    {
        return Id == ((User)obj).Id;
    }
    
    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}
```

Now the test will pass.


## CollectionAssert.AreEqual
If you want to check if two collections are identical, you can use `AreEqual`. This checks if the same elements are __in the same position__ in both collections.

For example this test will pass:
```csharp
[TestMethod]
public void AreEqual_Int()
{
    int[] array1 = new int[] { 1, 2, 3, 4, 5, 6 };
    int[] array2 = new int[] { 1, 2, 3, 4, 5, 6 };
    CollectionAssert.AreEqual(array1, array2); //OK
}
```

But the following will fail:
```csharp
[TestMethod]
public void AreEqual_DifferentPosition_Int()
{
    int[] array1 = new int[] { 1, 2, 3, 5, 4, 6 };
    int[] array2 = new int[] { 1, 2, 3, 4, 5, 6 };
    CollectionAssert.AreEqual(array1, array2); //KO
}

```

As we saw before, with simple objects it doesn't work:

```csharp
[TestMethod]
public void AreEqual_Objects()
{
    List<User> list = new List<User>()
    {
        new User(){ Username = "Elvis", Id=1},
        new User(){ Username="Janis", Id=2},
        new AdminUser(){ Username="Freddie", Id=3, Department="Legends"}
    };

    List<User> list2 = new List<User>()
    {
        new User(){ Username = "Elvis", Id=1},
        new User(){ Username="Janis", Id=2},
        new AdminUser(){ Username="Freddie", Id=3, Department="Legends"}
    };

    CollectionAssert.AreEqual(list, list2);
}
```

You have to use the `UpdatedUser` class in order to make it work.

```csharp
[TestMethod]
public void AreEqual_ObjectsWithOverride()
{
    List<UpdatedUser> list = new List<UpdatedUser>()
    {
        new UpdatedUser(){ Username = "Elvis", Id=1},
        new UpdatedUser(){ Username="Janis", Id=2}
    };

    List<UpdatedUser> list2 = new List<UpdatedUser>()
    {
        new UpdatedUser(){ Username = "Elvis", Id=1},
        new UpdatedUser(){ Username="Janis", Id=2}
    };

    CollectionAssert.AreEqual(list, list2);
}
```

What about structs? Well, you can imagine, everything is fine.

```csharp
[TestMethod]
public void AreEqual_Structs()
{
    List<Employee> list = new List<Employee>()
    {
        new Employee(){ Age = 11, Id=1},
        new Employee(){ Age= 92, Id=2}
    };

    List<Employee> list2 = new List<Employee>()
    {
        new Employee(){ Age = 11, Id=1},
        new Employee(){ Age= 92, Id=2}
    };

    CollectionAssert.AreEqual(list, list2);
}
```

## CollectionAssert.AreEquivalent
While `AreEqual` checks if two collections are identical, there is a more shallow way to test two collections. `AreEquivalent` controls if the same elements are in the two collections, __regardless of their position__.


```csharp
[TestMethod]
public void AreEquivalent_Int()
{
    int[] array1 = new int[] { 1, 2, 3, 4, 5, 6 };
    int[] array2 = new int[] { 4, 5, 6, 1, 2, 3 };
    CollectionAssert.AreEquivalent(array1, array2); //OK
}
```

## CollectionAssert.Contains
Ok, this method is easy to guess why it is used for...

```csharp
[TestMethod]
public void Contains_Int()
{
    int[] array1 = new int[] { 1, 2, 3, 4, 5, 6 };
    CollectionAssert.Contains(array1, 5); //OK
}
```

## CollectionAssert.IsSubsetOf
Even here, it's pretty easy.

```csharp
[TestMethod]
public void IsSubsetOf_Int()
{

    int[] array1 = new int[] { 1, 2, 3, 4, 5, 6 };
    int[] subset = new int[] { 2, 3 };
    CollectionAssert.IsSubsetOf(subset, array1); //OK
}

```

## Wrapping up
We had a review of the `CollectionAssert` class. I think it is very useful for checking if a collection is "well formed", checking for the type of the content and for the presence of an item. But it would be better have also a method for checking if a custom condition is respected by all the elements of the collection, for example specifying a lambda expression to be evaluated for each element.


## Conclusion
This is the end of this journey through pain and joy. As you can see, MSTest is fine for basic tests, but if you want something more complete I suggest to use other libraries.

My favorite, by now, is [FluentAssertion](https://fluentassertions.com). It replaces the `Assert` class with a syntax that allows you to create more complex tests. It is more readable (well, _fluent_) and a test looks like:

```csharp
[TestMethod]
public void MustContain()
{

    int[] array = new int[] { 1, 2, 3, 4, 5 };

    array.Should().Contain(4);
}
```

I think that MSTest is perfect if you are moving your first steps in the world of unit testing, but when the complexity grows you should consider adopting other frameworks.