1

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
    }
2
  • 1
    Parametrised test could be an option, but have a read here about it's not easy to do with MsTest. Commented Sep 6, 2016 at 13:02
  • @kayess this is interesting Commented Sep 8, 2016 at 12:47

1 Answer 1

3

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[]>));
   }
}
Sign up to request clarification or add additional context in comments.

8 Comments

Did you notice that OP uses MsTest and not NUnit??
@kayess What does NUnit have to do with my answer?
@ben First part of your answer is what I needed to eliminate. And Mock definitely I would use for dependencies, I am clear about that.
@Pacchy So you're trying to use a single unit test method to test several different sorting algorithms? Personally, I would write separate unit tests for each sorting algorithm because otherwise the test logic becomes a little obscured. Parameterized tests are meant more for specifying input values and expected values, but you could use a parameterized test to specify an integer identifier, and then create your ISort implementation based on that identifier. See this article blogs.msdn.microsoft.com/vstsqualitytools/2009/09/05/…
@Pacchy Or you could make a SortFactory, with a method that'll create all of your ISort implementations, and then loop your test on that method. But again, I don't recommend doing that. Unit tests should be as easy to read as possible, and conditionally creating different sorting algorithms obfuscates the test.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.