SyntaxStudy
Sign Up
C# Mocking with Moq and Integration Testing
C# Beginner 1 min read

Mocking with Moq and Integration Testing

Unit tests should test one class in isolation. Dependencies are replaced with mock objects that simulate the real implementation. Moq is the most popular mocking library for .NET; it uses lambda expressions to set up return values (`Setup`) and verify calls (`Verify`) with a clean, readable API. Integration tests exercise multiple layers together — typically a real database or an in-process web server. ASP.NET Core's `WebApplicationFactory` spins up the entire application in memory, lets you configure services differently (swap the real DB for an in-memory one), and provides an `HttpClient` to send test requests. Test coverage is a useful guide but not a goal in itself. Aim for meaningful tests that verify real behaviour rather than chasing 100% line coverage with trivial assertions. Use mutation testing tools like `Stryker.NET` to verify that your tests actually fail when the production code is changed.
Example
// Moq mocking + WebApplicationFactory integration test

using Moq;
using Xunit;
using Microsoft.AspNetCore.Mvc.Testing;

// ------- Unit test with Moq -------
public interface IOrderRepository
{
    Order? GetById(int id);
    void   Save(Order order);
}

public class OrderService
{
    private readonly IOrderRepository _repo;
    public OrderService(IOrderRepository repo) => _repo = repo;

    public string GetOrderStatus(int id)
    {
        var order = _repo.GetById(id);
        return order is null ? "Not Found" : order.Status;
    }
}

public record Order(int Id, string Status);

public class OrderServiceTests
{
    [Fact]
    public void GetOrderStatus_ExistingOrder_ReturnsStatus()
    {
        // Arrange
        var mockRepo = new Mock<IOrderRepository>();
        mockRepo.Setup(r => r.GetById(1))
                .Returns(new Order(1, "Shipped"));

        var service = new OrderService(mockRepo.Object);

        // Act
        string status = service.GetOrderStatus(1);

        // Assert
        Assert.Equal("Shipped", status);
        mockRepo.Verify(r => r.GetById(1), Times.Once);
    }

    [Fact]
    public void GetOrderStatus_MissingOrder_ReturnsNotFound()
    {
        var mockRepo = new Mock<IOrderRepository>();
        mockRepo.Setup(r => r.GetById(It.IsAny<int>())).Returns((Order?)null);

        var service = new OrderService(mockRepo.Object);
        Assert.Equal("Not Found", service.GetOrderStatus(99));
    }
}

// ------- Integration test with WebApplicationFactory -------
public class ProductApiTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly HttpClient _client;
    public ProductApiTests(WebApplicationFactory<Program> factory)
        => _client = factory.CreateClient();

    [Fact]
    public async Task GetProducts_ReturnsOkWithList()
    {
        var response = await _client.GetAsync("/api/products");
        response.EnsureSuccessStatusCode();
        string body = await response.Content.ReadAsStringAsync();
        Assert.Contains("Laptop", body);
    }
}

This is the last lesson in this section.

Create a free account to earn a certificate