Work in Progress
Diese Seite ist aktuell im Review! Die Seite wurde noch nicht qualitätsgesichert und kann Fehler enthalten.
Die verlinkten Seiten sind ggf. nur für Schleupen-Mitarbeiter sichtbar.

Fixture für Testklasse erstellen

Dieses Muster soll den Entwurf von Fixture-Klassen dokumentieren. Dabei stellt ein Fixture die Testumgebung bereit.

Design

Das Fixture hat eine 1:1-Beziehung zu der eigentlichen Testklasse. Außerdem kann das Fixture weitere wiederverwendbare Fixtures, z.B. zur Sitzungserzeugung Mocking, etc., verwenden.

Implementierung

Das Fixture stellt die Testumgebung bereit. Es ist als nested class innerhalb einer partiellen Klasse umzusetzen. Hier befinden sich auch die Setup- und Verify-Methoden zum Testaufbau und zur Prüfung der Testergebnisse. Die genaue Verwendung dieser Methoden ist in Testklassen für Unittests erstellen beschrieben.

Die Konstruktoren des Fixture werden oft auch aus der NUnit Infrastruktur aufgerufen (auch wenn der Test nur analyisiert und nicht durchgeführt wird) und sollten dementsprechend schnell sein (also z.B. keine Datenbankzugriffe tätigen).

BuecherAusleihenControllerTest.Fixture.cs
namespace Schleupen.AS.MT.BIB.Benutzerkonten;

internal sealed partial class BuecherAusleihenControllerTest
{
    private Fixture fixture;
    
    [SetUp]
	public void Setup() => fixture = new Fixture();

    [TearDown]
    public void Dispose() => fixture?.Dispose();
    
	private sealed class Fixture : IDisposable
	{
		public Mocks Mocks { get; } = new();

		public TestData TestData { get; } = new();

		public BuecherAusleihenController CreateTestObject()
		{
			return new BuecherAusleihenController(
				Mocks.BenutzerkontoRepositoryMock.Object,
				Mocks.BuchRepositoryMock.Object,
				Mocks.AusleiheRepositoryMock.Object,
				Mocks.DomainEventPublisherMock.Object);
		}

        public void Dispose()
        {
        }
	}

    private sealed class Mocks
	{
        public Mock<IReadOnlyBenutzerkontoRepository> BenutzerkontoRepositoryMock { get; } = new();

		public Mock<IReadOnlyBuchRepository> BuchRepositoryMock { get; } = new();

		public Mock<IAusleiheRepository> AusleiheRepositoryMock { get; } = new();

		public Mock<IDomainEventPublisher> DomainEventPublisherMock { get; } = new();
    }

    private sealed class TestData
    {
    }
}
BuecherAusleihenControllerTest.cs
namespace Schleupen.AS.MT.BIB.Benutzerkonten;

[TestFixture]
internal sealed partial class BuecherAusleihenControllerTest
{
	[Test]
	public void LeiheAusAsync_WhereBenutzerkontoDoesNotExist_ShouldThrowException()
	{
		BuecherAusleihenController testObject = fixture.CreateTestObject();
		AusleihAuftrag testInput = new(
			fixture.TestData.ExternalIdOfBenutzer,
			fixture.TestData.Buecher.Select(buch => buch.Id),
			null,
			DateTimeOffset.Now);

		Assert.Throws<ValidationException>(() => testObject.LeiheAusAsync(testInput).GetAwaiter().GetResult());
	}
}

Die Fixture-Klasse selber rekombiniert dabei andere Fixtures:

  • ein FachdatenFixture, das fachliche Objekte zur Verfügung stellt Persistenz-Fixture für Fachdaten erstellen
  • TransactionScopeFixture
  • SessionTokenFixture (Vorsicht: hat eine Abhängigkeit zur CS 33.0-Infrastruktur und kann daher nur im AIT eingesetzt werden)

Stärken und Schwächen

Stärken
  • Wiederverwendung von bereits vorhandenen Fixtures
  • Es ist einfacher, voneinander unabhängige Tests zu schreiben
  • Größere Übersichtlichkeit
Schwächen
  • Erhöhter Implementierungsaufwand

Benutzte Muster

Cookie Consent mit Real Cookie Banner