Skip to main content

How to determine if method is thread safe using Unit Tests.

# Unit Testing Thread-Safety In C#

This time I am going to show a simple example of how to determine if method is
thread safe using unit tests. With the approach described bellow you can verify
thread safety of a particular code block in your console app, windows store app,
windows phone app or almost any other application or project. Also this approach
might beneficial if your team practices Test Driven Development(TDD).

For my basic example, I have created a new Portable Library project(named
"Services") and a standard MS Unit Tests Project. Inside Services project I have
created a simple PopularNameService class, which represents a service for
storing popular names. This class has two public methods: "AddName" for adding a
new name to a list and "GetNamesCount" for returning the count of names
currently stored.

```csharp
public class PopularNameService
{
    private List<string> popularNames = new List<string>();

    public void AddName(string newPopularName)
    {
        popularNames.Add(newPopularName);
    }

    public int GetNamesCount()
    {
        return popularNames.Count;
    }
}
```

It is absolutely possible that AddName method will be called from different
threads within our application at the same time. So assuming the functionality
of AddName and GetNamesCount methods is already tested and verified, next step
would be to determine how thread safe those methods actually are. For this very
purpose I am going to create a unit test AddNameThreadSafetyTest, which will
internally run two separate threads and each of those threads will try to call
AddName method exactly 1000 times. After two threads are finished running, I am
going to assert if PopularNameService now contains a list of 2000 names. Keep in
mind that we need to call Join on each of the threads to wait till threads are
done executing before asserting test results.

```csharp
[TestClass]
public class PopularNameServiceTests
{
    private PopularNameService service;

    [TestInitialize]
    public void Setup()
    {
        service = new PopularNameService();
    }

    [TestMethod]
    public void AddNameThreadSafetyTest()
    {
        var t1 = new Thread(AddManyProducts);
        var t2 = new Thread(AddManyProducts);

        t1.Start();
        t2.Start();

        t1.Join();
        t2.Join();

        Assert.AreEqual(2000, service.GetNamesCount());
    }

    private void AddManyProducts()
    {
        for (int x = 0; x < 1000; x++)
        {
            var newName = string.Format("name {0}", x);
            service.AddName(newName);
        }
    }
}
```

After executing Unit Tests we are going to get a failed test with the following
error message: **Assert.AreEqual failed. Expected:. **Actual:**(Surprise! :)). (Note
that second number may vary depending on hardware specs). A method or a resource
is not locked properly while two different threads are trying to access it. This
leads to an obvious conclusion that AddName method isn't thread safe.

To fix this issue we might want to introduce a locking mechanism for a AddName
method. After updating the code for PopularNameService it will probably looks as
the one bellow:

```chsarp
public class PopularNameService
{
    private readonly Object popularNamesLock = new Object();

    private List<string> popularNames = new List<string>();

    public void AddName(string newPopularName)
    {
        lock (popularNamesLock)
        {
            popularNames.Add(newPopularName);
        }
    }

    public int GetNamesCount()
    {
        return popularNames.Count;
    }
}
```

There is also an option to use [thead-safe collections](http://msdn.microsoft.com/en-us/library/dd997305.aspx)
(which are part of .NET since 4.0), but not everything is available for
Portrable Class Library projects. Now after fixing the code for
PopularNameService, the unit test will pass successfully and the AddName
method can be considered thread safe.

---

**Source**

> [UNIT TESTING THREAD-SAFETY IN C#](https://jevgeni.net/2013/07/31/unit-testing-thread-safety-c/)