Section 3 of 5

Integration Testing

🎯 What You'll Learn

  • What is integration testing
  • Unit vs Integration tests
  • In-memory database
  • Testing with real dependencies
  • Test database setup

What is Integration Testing?

Integration testing tests how multiple components work together, including real dependencies like databases, APIs, and file systems.

Unit vs Integration Tests

Aspect Unit Tests Integration Tests
Scope Single unit (method/class) Multiple components
Dependencies Mocked Real
Speed Fast Slower
Isolation High Low
Purpose Verify logic Verify integration

In-Memory Database

Use an in-memory database for fast integration tests.

Install Package Bash
dotnet add package Microsoft.EntityFrameworkCore.InMemory
Setup In-Memory Database C#
public class ProductRepositoryTests
{
    private InvenTrackDbContext GetInMemoryContext()
    {
        var options = new DbContextOptionsBuilder<InvenTrackDbContext>()
            .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
            .Options;

        return new InvenTrackDbContext(options);
    }
}

InvenTrack Integration Test Example

ProductRepositoryTests.cs C#
public class ProductRepositoryTests
{
    [Fact]
    public async Task Add_Product_SavesToDatabase()
    {
        // Arrange
        using var context = GetInMemoryContext();
        var repository = new ProductRepository(context);
        var product = new Product { Name = "Laptop", Price = 999 };

        // Act
        await repository.AddAsync(product);
        await context.SaveChangesAsync();

        // Assert
        var saved = await context.Products.FindAsync(product.Id);
        Assert.NotNull(saved);
        Assert.Equal("Laptop", saved.Name);
    }

    [Fact]
    public async Task GetById_ExistingProduct_ReturnsProduct()
    {
        // Arrange
        using var context = GetInMemoryContext();
        var product = new Product { Name = "Mouse", Price = 25 };
        context.Products.Add(product);
        await context.SaveChangesAsync();

        var repository = new ProductRepository(context);

        // Act
        var result = await repository.GetByIdAsync(product.Id);

        // Assert
        Assert.NotNull(result);
        Assert.Equal("Mouse", result.Name);
    }

    private InvenTrackDbContext GetInMemoryContext()
    {
        var options = new DbContextOptionsBuilder<InvenTrackDbContext>()
            .UseInMemoryDatabase(Guid.NewGuid().ToString())
            .Options;

        return new InvenTrackDbContext(options);
    }
}

Key Takeaways

  • Integration tests: Test multiple components together
  • Real dependencies: Use actual database, not mocks
  • In-memory database: Fast, isolated tests
  • Guid.NewGuid(): Unique database per test
  • Slower than unit tests: But more realistic