Autofixture: Das Einfrieren eines Mocks überschreibt eine injizierte Instanz nicht

Erstellt am 31. Juli 2018  ·  1Kommentar  ·  Quelle: AutoFixture/AutoFixture

Aktuelles Verhalten

Beim Injizieren von zwei konkreten Instanzen überschreibt die zweite Instanz die erste.

Beim Injizieren einer konkreten Instanz gefolgt von einer simulierten Instanz überschreibt die zweite Instanz die erste nicht.

Dies macht die Idee, einige Tests durchzuführen, die einen Mock verwenden, und einige Tests, die eine Implementierung verwenden (mit einem Testklassenkonstruktor, um eine Befestigung zwischen Tests zu teilen) ziemlich umständlich.

Erwartetes Verhalten

Beim Injizieren von zwei konkreten Instanzen überschreibt die zweite Instanz die erste.

Beim Injizieren einer konkreten Instanz, gefolgt von einer simulierten Instanz, überschreibt die zweite Instanz die erste.

Beispiel für erwartetes Verhalten

```C#
mit System.Collections.Generic;
Verwenden von AutoFixture;
mit AutoFixture.AutoMoq;
unter Verwendung von Moq;
mit Xunit;

Namespace SomeNamespace
{
öffentliche Klasse AutoFixtureTests
{
[Tatsache]
// Geht vorbei
public void Should_OverridePreviouslyInjectedString()
{
const string test1 = "test1";
const string test2 = "test2";

        var fixture = new Fixture();

        fixture.Inject(test1);
        fixture.Inject(test2);

        Assert.Equal(fixture.Create<string>(), test2);
    }

    [Fact]
    // Fails
    public void Should_OverridePreviouslyInjectedInstance()
    {
        var fixture = new Fixture().Customize(new AutoMoqCustomization());

        var sut1 = new List<int>();

        fixture.Inject<IList<int>>(sut1);
        fixture.Freeze<Mock<IList<int>>>();

        var sut2 = fixture.Create<IList<int>>();

        Assert.NotSame(sut1, sut2);
    }
}

}
```

question

Hilfreichster Kommentar

Hallo @charles-lachs,

Vielen Dank, dass Sie sich die Zeit genommen haben, dies zu melden.

Das Verhalten, das Sie beobachten, ist _by design_. Erlauben Sie mir zu erklären. 🙂

Wenn Sie sich die Implementierung der Methode Freeze<T> ansehen:

var value = fixture.Create<T>();
fixture.Inject(value);
return value;

Sie werden sehen, dass es lediglich ein Exemplar von T und es in das Gerät injiziert. Tatsächlich ist die Methode Freeze eine praktische Abkürzung für genau diesen Vorgang. Wie @ploeh in seinem Beitrag zur Einführung der Freeze-Methode im Jahr 2010 schrieb:

Es stellte sich heraus, dass wir dieses Codierungsidiom so häufig verwendet haben, dass wir beschlossen haben, es in einer praktischen Methode zu kapseln. Nach einigen Diskussionen kamen wir auf den Namen Freeze, da wir im Wesentlichen eine einzelne anonyme Variable im Gerät einfrieren und den Standardalgorithmus zum Erstellen neuer Instanzen umgehen.

Angesichts dessen sollte es nicht überraschen, dass das Einfrieren desselben Typs T wie eine injizierte Instanz dieselbe Instanz ergibt.

Um nun auf Ihren Punkt einzugehen:

Dies macht die Idee, einige Tests durchzuführen, die einen Mock verwenden, und einige Tests, die eine Implementierung verwenden (mit einem Testklassenkonstruktor, um eine Befestigung zwischen Tests zu teilen) ziemlich umständlich.

Da ein Fixture den _Kontext_ repräsentiert, in dem ein Test ausgeführt wird, _können_ Sie sicherlich mehrere Tests dieselbe Fixture verwenden ; Dies geht jedoch auf Kosten der Vermischung mehrerer – und möglicherweise widersprüchlicher – Bedenken.

Das xUnit Patterns-Buch fasst es gut zusammen :

Das größte Problem bei einem gemeinsam genutzten Gerät besteht darin, dass es zu "Kollisionen" zwischen Tests kommen kann, die möglicherweise zu fehlerhaften Tests führen , da Tests von den Ergebnissen anderer Tests abhängen können. Ein weiteres Problem besteht darin, dass ein Fixture, das für viele Tests entwickelt wurde, zwangsläufig viel komplizierter ist als das für einen einzelnen Test erforderliche Minimal Fixture .

Diese "Kollision" ist genau das, was passiert, wenn ein Test erwartet, dass ein Objekt vom Typ T eine bestimmte Instanz ist, während ein anderer Test erwartet, dass es sich bei T um ein gefälschtes Objekt handelt .

Da mir kein Testszenario einfällt, bei dem es für den gleichen Typ T Sinn macht, sowohl ein Schein _als auch_ eine konkrete Instanz zu sein (obwohl ich gerne falsch bewiesen werde), schlage ich vor, dass Sie diese haben Tests verwenden verschiedene Vorrichtungen, von denen jede so konfiguriert ist, dass sie ihr spezielles Szenario erfüllt.

>Alle Kommentare

Hallo @charles-lachs,

Vielen Dank, dass Sie sich die Zeit genommen haben, dies zu melden.

Das Verhalten, das Sie beobachten, ist _by design_. Erlauben Sie mir zu erklären. 🙂

Wenn Sie sich die Implementierung der Methode Freeze<T> ansehen:

var value = fixture.Create<T>();
fixture.Inject(value);
return value;

Sie werden sehen, dass es lediglich ein Exemplar von T und es in das Gerät injiziert. Tatsächlich ist die Methode Freeze eine praktische Abkürzung für genau diesen Vorgang. Wie @ploeh in seinem Beitrag zur Einführung der Freeze-Methode im Jahr 2010 schrieb:

Es stellte sich heraus, dass wir dieses Codierungsidiom so häufig verwendet haben, dass wir beschlossen haben, es in einer praktischen Methode zu kapseln. Nach einigen Diskussionen kamen wir auf den Namen Freeze, da wir im Wesentlichen eine einzelne anonyme Variable im Gerät einfrieren und den Standardalgorithmus zum Erstellen neuer Instanzen umgehen.

Angesichts dessen sollte es nicht überraschen, dass das Einfrieren desselben Typs T wie eine injizierte Instanz dieselbe Instanz ergibt.

Um nun auf Ihren Punkt einzugehen:

Dies macht die Idee, einige Tests durchzuführen, die einen Mock verwenden, und einige Tests, die eine Implementierung verwenden (mit einem Testklassenkonstruktor, um eine Befestigung zwischen Tests zu teilen) ziemlich umständlich.

Da ein Fixture den _Kontext_ repräsentiert, in dem ein Test ausgeführt wird, _können_ Sie sicherlich mehrere Tests dieselbe Fixture verwenden ; Dies geht jedoch auf Kosten der Vermischung mehrerer – und möglicherweise widersprüchlicher – Bedenken.

Das xUnit Patterns-Buch fasst es gut zusammen :

Das größte Problem bei einem gemeinsam genutzten Gerät besteht darin, dass es zu "Kollisionen" zwischen Tests kommen kann, die möglicherweise zu fehlerhaften Tests führen , da Tests von den Ergebnissen anderer Tests abhängen können. Ein weiteres Problem besteht darin, dass ein Fixture, das für viele Tests entwickelt wurde, zwangsläufig viel komplizierter ist als das für einen einzelnen Test erforderliche Minimal Fixture .

Diese "Kollision" ist genau das, was passiert, wenn ein Test erwartet, dass ein Objekt vom Typ T eine bestimmte Instanz ist, während ein anderer Test erwartet, dass es sich bei T um ein gefälschtes Objekt handelt .

Da mir kein Testszenario einfällt, bei dem es für den gleichen Typ T Sinn macht, sowohl ein Schein _als auch_ eine konkrete Instanz zu sein (obwohl ich gerne falsch bewiesen werde), schlage ich vor, dass Sie diese haben Tests verwenden verschiedene Vorrichtungen, von denen jede so konfiguriert ist, dass sie ihr spezielles Szenario erfüllt.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

mjfreelancing picture mjfreelancing  ·  4Kommentare

ploeh picture ploeh  ·  7Kommentare

zvirja picture zvirja  ·  4Kommentare

DeafLight picture DeafLight  ·  5Kommentare

malylemire1 picture malylemire1  ·  7Kommentare