Pacchy
Pacchy

Reputation: 73

Using DI for Unit Testing

I understand using DI for dependencies and mocking them for unit tests. However when I have multiple implementations for the current feature which I am unit testing how do I inject them into the unit test.

Ex: QuickSort or MergeSort

public class TestSort
{
  ISort sort = null;
    [TestInitialize]
    public void Setup()
    {
        sort = new MergeSort(); // or any implementation which need to be injected on setup
    }

Upvotes: 1

Views: 515

Answers (1)

Ben Rubin
Ben Rubin

Reputation: 7341

If you want to test your "sort" methods, you should have separate unit tests for each sorting algorithm. For example

[TestMethod]
public void MergeSort_SortUnderorderedList_ShouldSortListCorrectly()
{
   // Arrange
   ISort sort = new MergeSort();

   // Act
   int[] sortedList = sort.Sort(new int[] { 4, 2, 18, 5, 19 });

   // Assert
   Assert.AreEqual(2, sortedList[0]);
   Assert.AreEqual(4, sortedList[1]);
   Assert.AreEqual(5, sortedList[2]);
   Assert.AreEqual(18, sortedList[3]);
   Assert.AreEqual(19, sortedList[4]);      
}

[TestMethod]
public void QuickSort_SortUnderorderedList_ShouldSortListCorrectly()
{
   // Arrange
   ISort sort = new QuickSort();

   // Act
   int[] sortedList = sort.Sort(new int[] { 4, 2, 18, 5, 19 });

   // Assert
   Assert.AreEqual(2, sortedList[0]);
   Assert.AreEqual(4, sortedList[1]);
   Assert.AreEqual(5, sortedList[2]);
   Assert.AreEqual(18, sortedList[3]);
   Assert.AreEqual(19, sortedList[4]);   
}

When you're writing your tests for a class which you inject a sorting algorithm into, you shouldn't be testing whether the sorting algorithm works correctly in that test. Instead, you should inject a sorting algorithm mock and test that the Sort() method is called (but not test for the correct results of the sorting algorithm in that test).

This example uses Moq to do mocking

public class MyClass
{
   private readonly ISort sortingAlgorithm;

   public MyClass(ISort sortingAlgorithm)
   {
      if (sortingAlgorithm == null)
      {
         throw new ArgumentNullException("sortingAlgorithm");
      }
      this.sortingAlgorithm = sortingAlgorithm;
   }

   public void DoSomethingThatRequiresSorting(int[] list)
   {
      int[] sortedList = this.sortingAlgorithm.Sort(list);

      // Do stuff with sortedList
   }
}

[TestClass]
public class MyClassTests
{
   [TestMethod]
   public void DoSomethingThatRequiresSorting_SomeCondition_ExpectedResult()
   {
      // Arrange - I assume that you need to use the result of Sort() in the 
      // method that you're testing, so the Setup method causes sortingMock 
      // to return the specified list when Sort() is called
      ISort sortingMock = new Mock<ISort>();
      sortingMock.Setup(e => e.Sort().Returns(new int[] { 2, 5, 6, 9 }));
      MyClass myClass = new MyClass(sortingMock.Object);

      // Act 
      myClass.DoSomethingThatRequiresSorting(new int[] { 5, 9, 2, 6 });

      // Assert - check that the Sort() method was called
      myClass.Verify(e => e.Sort(It.IsAny<int[]>));
   }
}

Upvotes: 3

Related Questions