Unit Testing Application Layer w .NET

Unit Testing Application Layer w .NET – Mockowanie zależności z Moq [Część 13]

Unit Testing Application Layer w .NET – Mockowanie zależności z Moq

Testowanie Application Layer w .NET to moment, w którym wielu programistów zaczyna improwizować. Klasy mają zależności, pojawiają się repository, serwisy, pliki… a testy nagle przestają być unit. W tym artykule pokażę Ci jak testować Application Layer poprawnie, używając mockowania z Moq, na realnym przykładzie GameService. Bez teorii dla teorii. Z kodem, który działa i skaluje się w projektach enterprise.

Czym jest Application Layer w Clean Architecture?

Application Layer to orkiestrator przypadków użycia. Nie zawiera logiki biznesowej (to rola Core), ani dostępu do danych (Infrastructure). Jego zadaniem jest:

  • koordynowanie współpracy komponentów
  • walidacja wejścia i flow aplikacji
  • delegowanie pracy do odpowiednich serwisów

👉 To właśnie dlatego Application Layer zawsze ma zależności – i właśnie dlatego jego testowanie jest trudniejsze.

Zobacz też: Czym jest Clean Architecture w .NET

Dlaczego bez mocków to nie są unit testy?

Jeśli w teście Application Layer:

  • używasz prawdziwego Repository
  • czytasz pliki z dysku
  • uruchamiasz prawdziwy BattleService

…to nie piszesz unit testów, tylko testy integracyjne.

Problemy testów bez mocków:

  • ❌ wolne (I/O, Thread.Sleep)
  • ❌ niestabilne (pliki, dane testowe)
  • ❌ testują kilka klas naraz
  • ❌ bug w innej warstwie psuje test

Rozwiązanie? Mockowanie zależności.

Czym jest mock i po co go używamy?

Mock to kontrolowana, fake’owa implementacja interfejsu, której zachowanie definiujesz w teście.

Dzięki mockom możesz:

  • ustalić co metoda ma zwrócić (Setup)
  • sprawdzić czy została wywołana (Verify)
  • zasymulować błędy (Throws)

W .NET najczęściej używamy do tego biblioteki Moq.


Przykład: GameService w Application Layer

GameService zależy od:

  • IPostacRepository
  • IBattleService
public class GameService : IGameService
{
    private readonly IPostacRepository _postacRepository;
    private readonly IBattleService _battleService;
    private List<Postac> _postacie = new();

    public IReadOnlyList<Postac> Postacie => _postacie.AsReadOnly();

    public GameService(IPostacRepository postacRepository, IBattleService battleService)
    {
       _postacRepository = postacRepository;
       _battleService = battleService;
    }
    ...
}

👉 Naszym celem jest przetestować GameService w izolacji, bez prawdziwych implementacji.


Setup testów – fundament Application Layer Testing

Zanim napiszemy pierwszy test, robimy trzy rzeczy:

  • mock każdej zależności
  • brak new dla prawdziwych klas
  • jedna testowana klasa
public class GameServiceTests
{
   private readonly Mock<IPostacRepository> _mockRepository;
   private readonly Mock<IBattleService> _mockBattleService;
   private readonly GameService _gameService;

   public GameServiceTests()
   {
      _mockRepository = new Mock<IPostacRepository>();
      _mockBattleService = new Mock<IBattleService>();
      _gameService = new GameService(_mockRepository.Object, _mockBattleService.Object);
   }
   ...
}

To jest święta trójca unit testów Application Layer.

Test 1: delegacja do Repository (happy path)

[Fact]
public void PobierzPostacie_WithValidPath_ShouldLoadCharacters()
{
   // Arrange
   var expectedCharacters = new List<Postac>
   {
      new Wojownik("Test Warrior"),
      new Mag("Test Mage")
   };

   var testFilePath = Path.GetTempFileName();

   _mockRepository.Setup(r => r.PobierzPostacie(testFilePath))
      .Returns(expectedCharacters);

   // Act
   _gameService.PobierzPostacie(testFilePath);

   // Assert
   _gameService.Postacie.Should().HaveCount(2);
   _gameService.Postacie.Should().BeEquivalentTo(expectedCharacters);
   _mockRepository.Verify(r => r.PobierzPostacie(testFilePath), Times.Once);

   // Cleanup
   File.Delete(testFilePath);
}

✔ test delegacji ✔ test stanu ✔ pełna izolacja

Verify – najważniejsze narzędzie w Application Layer

Verify() pozwala sprawdzić:

  • czy metoda została wywołana
  • ile razy (Times.Once, Times.Never)
  • z jakimi parametrami (It.Is<T>)

To są testy kontraktu i architektury, nie tylko funkcjonalności.


Najczęstsze błędy przy testowaniu Application Layer

Checklist:

  • ❌ testowanie implementacji zamiast zachowania
  • ❌ brak mocków
  • ❌ testowanie kilku klas naraz
  • ❌ brak Verify
  • ❌ logika biznesowa w Application Layer

Jeśli test trudno napisać → design jest problemem.

Podsumowanie

Testowanie Application Layer w .NET:

  • wymaga mockowania zależności
  • wymusza dobry design
  • chroni architekturę
  • daje szybkie i stabilne testy

To nie jest „zaawansowane testowanie”. To podstawa pracy zawodowego .NET developera.

👉 Zostaw komentarz – z czym masz największy problem przy testach?
👉 Sprawdź też: Unit Testing Core Layer w .NET

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *