Back to Curriculum

Unit Testing with MSTest

📚 Lesson 13 of 15 ⏱️ 50 min

Unit Testing with MSTest

50 min

Unit testing is essential for code quality and maintainability, enabling you to verify that individual units of code work correctly. Unit tests are fast, isolated, and repeatable. They catch bugs early, enable refactoring with confidence, and document expected behavior. Understanding unit testing enables professional development. Unit testing is essential for reliable software.

MSTest is Microsoft's testing framework for .NET, providing attributes, assertions, and test execution infrastructure. MSTest is integrated with Visual Studio and supports parallel test execution. Test classes use [TestClass] attribute. Test methods use [TestMethod] attribute. Understanding MSTest enables writing tests. MSTest is one of several .NET testing frameworks.

Test methods are marked with [TestMethod] attribute and contain test logic with assertions. Test methods should be public, void, and parameterless. Tests follow Arrange-Act-Assert pattern: set up data, execute code, verify results. Understanding test structure enables effective testing. Test structure is important for maintainability.

Assertions verify expected behavior and outcomes, using methods like Assert.AreEqual, Assert.IsTrue, Assert.IsNull, etc. Assertions fail tests when conditions aren't met. Multiple assertions can be used in a single test. Understanding assertions enables verifying behavior. Assertions are the core of testing.

Test organization includes test classes, test methods, setup/teardown methods ([TestInitialize], [TestCleanup]), and test data. Good organization makes tests maintainable. Setup methods prepare test environment. Teardown methods clean up. Understanding test organization enables maintainable test suites. Test organization is important for large projects.

Best practices include writing tests before or alongside code (TDD), keeping tests independent, using meaningful test names, testing edge cases, and maintaining high test coverage. Understanding unit testing enables reliable, maintainable code. Unit testing is essential for professional development.

Key Concepts

  • Unit testing is essential for code quality and maintainability.
  • MSTest is Microsoft's testing framework for .NET.
  • Test methods are marked with [TestMethod] attribute.
  • Assertions verify expected behavior and outcomes.
  • Tests follow Arrange-Act-Assert pattern.

Learning Objectives

Master

  • Writing unit tests with MSTest
  • Using test attributes and assertions
  • Organizing test classes and methods
  • Following testing best practices

Develop

  • Test-driven development thinking
  • Understanding testing strategies
  • Writing maintainable test suites

Tips

  • Write tests before or alongside code (TDD).
  • Keep tests independent—don't rely on test execution order.
  • Use meaningful test names that describe what's being tested.
  • Test edge cases and error conditions.

Common Pitfalls

  • Not writing tests, making refactoring risky.
  • Writing tests that depend on each other.
  • Not testing edge cases, missing bugs.
  • Not maintaining tests, causing them to become outdated.

Summary

  • Unit testing is essential for code quality.
  • MSTest provides testing framework for .NET.
  • Test methods verify expected behavior.
  • Understanding unit testing enables reliable code.
  • Unit testing is essential for professional development.

Exercise

Write unit tests for a simple calculator class using MSTest.

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

public class Calculator
{
    public int Add(int a, int b) => a + b;
    public int Subtract(int a, int b) => a - b;
    public int Multiply(int a, int b) => a * b;
    public double Divide(int a, int b)
    {
        if (b == 0)
            throw new DivideByZeroException("Cannot divide by zero");
        return (double)a / b;
    }
}

[TestClass]
public class CalculatorTests
{
    private Calculator _calculator;
    
    [TestInitialize]
    public void Setup()
    {
        _calculator = new Calculator();
    }
    
    [TestMethod]
    public void Add_TwoPositiveNumbers_ReturnsCorrectSum()
    {
        // Arrange
        int a = 5, b = 3;
        
        // Act
        int result = _calculator.Add(a, b);
        
        // Assert
        Assert.AreEqual(8, result);
    }
    
    [TestMethod]
    public void Subtract_TwoNumbers_ReturnsCorrectDifference()
    {
        // Arrange
        int a = 10, b = 4;
        
        // Act
        int result = _calculator.Subtract(a, b);
        
        // Assert
        Assert.AreEqual(6, result);
    }
    
    [TestMethod]
    public void Multiply_TwoNumbers_ReturnsCorrectProduct()
    {
        // Arrange
        int a = 6, b = 7;
        
        // Act
        int result = _calculator.Multiply(a, b);
        
        // Assert
        Assert.AreEqual(42, result);
    }
    
    [TestMethod]
    public void Divide_TwoNumbers_ReturnsCorrectQuotient()
    {
        // Arrange
        int a = 10, b = 2;
        
        // Act
        double result = _calculator.Divide(a, b);
        
        // Assert
        Assert.AreEqual(5.0, result);
    }
    
    [TestMethod]
    [ExpectedException(typeof(DivideByZeroException))]
    public void Divide_ByZero_ThrowsException()
    {
        // Arrange
        int a = 10, b = 0;
        
        // Act
        _calculator.Divide(a, b);
        
        // Assert is handled by ExpectedException
    }
}

// Note: This would typically be in a separate test project
// and would require MSTest NuGet package
class Program
{
    static void Main(string[] args)
    {
        // Manual test execution
        var calculator = new Calculator();
        
        Console.WriteLine($"5 + 3 = {calculator.Add(5, 3)}");
        Console.WriteLine($"10 - 4 = {calculator.Subtract(10, 4)}");
        Console.WriteLine($"6 * 7 = {calculator.Multiply(6, 7)}");
        Console.WriteLine($"10 / 2 = {calculator.Divide(10, 2)}");
        
        try
        {
            calculator.Divide(10, 0);
        }
        catch (DivideByZeroException ex)
        {
            Console.WriteLine($"Exception caught: {ex.Message}");
        }
    }
}

Code Editor

Output