Freigeben über


Codegenerierungs-, Kompilierungs- und Benennungskonventionen in Microsoft Fakes

In diesem Artikel werden Optionen und Probleme bei der Generierung und Kompilierung von Fakes-Code erläutert und die Benennungskonventionen für gefälschte, generierte Typen, Member und Parameter beschrieben.

Anforderungen

  • Visual Studio Enterprise

  • Ein .NET Framework-Projekt

  • .NET Core, .NET 5.0 oder höher und SDK-Projekte bieten eine Vorschauunterstützung in Visual Studio 2019 Update 6 und sind in Update 8 standardmäßig aktiviert. Weitere Informationen finden Sie unter Microsoft Fakes für .NET Core- und SDK-Stilprojekte.

Codegenerierung und Kompilierung

Konfigurieren der Stub-Code-Generierung

Die Generierung von Stubtypen wird in einer XML-Datei konfiguriert, die die Dateierweiterung ".fakes " aufweist. Das Fakes-Framework integriert sich in den Build-Vorgang über benutzerdefinierte MSBuild-Aufgaben und erkennt diese Dateien zum Build-Zeitpunkt. Der Codegenerator "Fakes" kompiliert die Stubtypen in einer Assembly und fügt den Verweis auf das Projekt hinzu.

Im folgenden Beispiel werden Stubtypen veranschaulicht, die in FileSystem.dlldefiniert sind:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
    <Assembly Name="FileSystem"/>
</Fakes>

Typfilterung

Filter können in der .fakes-Datei festgelegt werden, um einzuschränken, welche Typen gestubbt werden sollen. Sie können eine ungebundene Anzahl von Clear-, Add-, Remove-Elementen unter dem StubGeneration-Element hinzufügen, um die Liste der ausgewählten Typen zu erstellen.

Beispielsweise generiert die folgende .fakes-Datei Stubs für Typen unter den Namensräumen System und System.IO, schließt jedoch jeden Typ im System aus, der "Handle" enthält:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
  <Assembly Name="mscorlib" />
  <!-- user code -->
  <StubGeneration>
    <Clear />
    <Add Namespace="System!" />
    <Add Namespace="System.IO!"/>
    <Remove TypeName="Handle" />
  </StubGeneration>
  <!-- /user code -->
</Fakes>

Die Filterzeichenfolgen verwenden eine einfache Grammatik, um zu definieren, wie der Abgleich erfolgen soll:

  • Filter sind standardmäßig nicht groß-/kleinschreibungssensitiv; Filter führen eine Teilzeichenfolgenübereinstimmung durch.

    el entspricht "Hello"

  • Durch das Hinzufügen von ! zum Ende des Filters wird eine genaue Übereinstimmung mit Groß- und Kleinschreibung erreicht:

    el! stimmt nicht mit "hello" überein.

    hello! entspricht "Hello"

  • Das Hinzufügen von * an das Ende des Filters lässt es mit dem Präfix der Zeichenfolge übereinstimmen.

    el* stimmt nicht mit "hello" überein.

    he* entspricht "Hello"

  • Mehrere Filter in einer durch Semikolons getrennten Liste werden als Disjunktion kombiniert:

    el;wo entspricht "Hallo" und "Welt"

Stubbetonklassen und virtuelle Methoden

Standardmäßig werden Stubtypen für alle nicht versiegelten Klassen generiert. Es ist möglich, die Stubtypen auf abstrakte Klassen durch die KONFIGURATIONSdatei ".fakes " einzuschränken:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/">
  <Assembly Name="mscorlib" />
  <!-- user code -->
  <StubGeneration>
    <Types>
      <Clear />
      <Add AbstractClasses="true"/>
    </Types>
  </StubGeneration>
  <!-- /user code -->
</Fakes>

Interne Typen

Der Fakes-Codegenerator generiert Shimtypen und Stubtypen für Typen, die für die generierte Fakes-Assembly sichtbar sind. Um interne Typen einer shimmed Assembly für Fakes und Ihre Testassembly sichtbar zu machen, fügen Sie InternalsVisibleToAttribute dem shimmed Assembly-Code Attribute hinzu, die die generierte Fakes-Assembly und die Testassembly sichtbar machen. Ein Beispiel:

// FileSystem\AssemblyInfo.cs
[assembly: InternalsVisibleTo("FileSystem.Fakes")]
[assembly: InternalsVisibleTo("FileSystem.Tests")]

Interne Typen in stark benannten Assemblys

Wenn die shimmed-Assembly stark benannt ist und Sie auf interne Typen der Assembly zugreifen möchten:

  • Sowohl Ihre Testassembly als auch die Fakes-Assembly müssen stark benannt werden.

  • Fügen Sie die öffentlichen Schlüssel der Test- und Fakes-Assembly zu den InternalsVisibleToAttribute-Attributen in den Shimmed-Assemblies hinzu. So würden die Beispielattribute im Shimmed-Assemblycode aussehen, wenn die shimmed-Assembly stark benannt ist:

    // FileSystem\AssemblyInfo.cs
    [assembly: InternalsVisibleTo("FileSystem.Fakes",
        PublicKey=<Fakes_assembly_public_key>)]
    [assembly: InternalsVisibleTo("FileSystem.Tests",
        PublicKey=<Test_assembly_public_key>)]
    

Wenn die shimmed Assembly stark benannt ist, signiert das Fakes Framework automatisch die generierte Fakes-Assembly. Sie müssen die Testassembly stark signieren. Siehe Strong-Named Assemblys.

Das Fakes-Framework verwendet denselben Schlüssel, um alle generierten Assemblys zu signieren, sodass Sie diesen Codeausschnitt als Ausgangspunkt verwenden können, um das InternalsVisibleTo-Attribut für die gefälschte Assembly zu Ihrem shimmed Assembly-Code hinzuzufügen.

[assembly: InternalsVisibleTo("FileSystem.Fakes, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e92decb949446f688ab9f6973436c535bf50acd1fd580495aae3f875aa4e4f663ca77908c63b7f0996977cb98fcfdb35e05aa2c842002703cad835473caac5ef14107e3a7fae01120a96558785f48319f66daabc862872b2c53f5ac11fa335c0165e202b4c011334c7bc8f4c4e570cf255190f4e3e2cbc9137ca57cb687947bc")]

Sie können einen anderen öffentlichen Schlüssel für die Fakes-Assembly angeben, z. B. einen Schlüssel, den Sie für die shimmed Assembly erstellt haben, indem Sie den vollständigen Pfad zur SNK-Datei angeben, der den alternativen Schlüssel als KeyFile Attributwert imFakes\CompilationElement der .fakes-Datei enthält. Beispiel:

<-- FileSystem.Fakes.fakes -->
<Fakes ...>
  <Compilation KeyFile="full_path_to_the_alternate_snk_file" />
</Fakes>

Anschließend müssen Sie den öffentlichen Schlüssel der alternativen SNK-Datei als zweiten Parameter des InternalVisibleTo-Attributs für die Fakes-Assembly im Shimmed-Assemblycode verwenden:

// FileSystem\AssemblyInfo.cs
[assembly: InternalsVisibleTo("FileSystem.Fakes",
    PublicKey=<Alternate_public_key>)]
[assembly: InternalsVisibleTo("FileSystem.Tests",
    PublicKey=<Test_assembly_public_key>)]

Im obigen Beispiel können die Werte Alternate_public_key und die Test_assembly_public_key Werte identisch sein.

Optimieren von Buildzeiten

Die Kompilierung von Fakes-Assemblies kann Ihre Buildzeit erheblich erhöhen. Sie können die Erstellungszeit minimieren, indem Sie die Fakes-Assemblys für .NET-Systemassemblys und Assemblys von Drittanbietern in einem separaten zentralisierten Projekt generieren. Da sich solche Assemblys selten auf Ihrem Computer ändern, können Sie die generierten Fakes-Assemblys in anderen Projekten wiederverwenden.

Fügen Sie aus Ihren Komponententestprojekten einen Verweis auf die kompilierten Fakes-Assemblys hinzu, die unter "FakesAssemblies" im Projektordner platziert werden.

  1. Erstellen Sie eine neue Klassenbibliothek mit der .NET-Laufzeitversion, die Ihren Testprojekten entspricht. Nennen wir es Fakes.Prebuild. Entfernen Sie die class1.cs Datei aus dem Projekt, nicht erforderlich.

  2. Fügen Sie einen Verweis auf alle System- und Drittanbieterassemblies hinzu, für die Sie Fakes benötigen.

  3. Fügen Sie für jede der Assemblys eine .fakes-Datei hinzu und bauen Sie.

  4. Aus Ihrem Testprojekt

    • Stellen Sie sicher, dass Sie einen Verweis auf die Fakes Runtime DLL haben:

      %ProgramFiles(x86)%\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\PublicAssemblies\Microsoft.QualityTools.Testing.Fakes.dll

    • Fügen Sie für jede Assembly, für die Sie Fakes erstellt haben, einen Verweis auf die entsprechende DLL-Datei im Ordner "Fakes.Prebuild\FakesAssemblies " Ihres Projekts hinzu.

Vermeiden von Zusammenstößen mit Assemblynamen

In einer Teambuildumgebung werden alle Buildausgaben in einem einzigen Verzeichnis zusammengeführt. Wenn mehrere Projekte Fakes verwenden, kann es passieren, dass Fakes-Assemblys aus verschiedenen Versionen sich gegenseitig überschreiben. Beispielsweise würden sowohl TestProject1, bei dem die mscorlib.dll des .NET Frameworks 2.0 gefälscht wird, als auch TestProject2, bei dem die mscorlib.dll für das .NET Framework 4 gefälscht wird, zu einer mscorlib.Fakes.dll Fakes-Assembly führen.

Um dieses Problem zu vermeiden, sollte Fakes automatisch versionsqualifizierte Assemblynamen für Nicht-Projekt-Verweise erstellen, wenn die .fakes Dateien hinzugefügt werden. Ein versionsqualifizierter Fakes-Assemblyname bettet eine Versionsnummer ein, wenn Sie den Namen der Fakes-Assembly erstellen:

Angesichts einer Assembly MyAssembly und einer Version 1.2.3.4 lautet der Name der Fakes-Assembly "MyAssembly.1.2.3.4.Fakes".

Sie können diese Version ändern oder entfernen, indem Sie das Versionsattribut des Assembly-Elements in den .fakes bearbeiten:

attribute of the Assembly element in the .fakes:
<Fakes ...>
  <Assembly Name="MyAssembly" Version="1.2.3.4" />
  ...
</Fakes>

Gefälschte Namenskonventionen

Benennungskonventionen für Shim- und Stubtypen

Namespaces

  • Das Suffix .Fakes wird dem Namespace hinzugefügt.

    Der Namespace System.Fakes enthält beispielsweise die Shim-Typen des System-Namespaces.

  • Global.Fakes enthält den Shim-Typ eines leeren Namespaces.

    Typnamen

  • Shim-Präfix wird dem Typnamen hinzugefügt, um den Shim-Typnamen zu erstellen.

    ShimExample ist z. B. der Shim-Typ des Beispieltyps.

  • Das Stubpräfix wird dem Typnamen hinzugefügt, um den Stubtypnamen zu erstellen.

    StubIExample ist z. B. der Stubtyp des IExample-Typs.

    Typargumente und geschachtelte Typstrukturen

  • Generische Typargumente werden kopiert.

  • Verschachtelte Typenstruktur wird für Shim-Typen kopiert.

Benennungskonventionen für Shim-Delegat- oder Stubdelegatfelder

Grundlegende Regeln für die Feldbenennung, beginnend mit einem leeren Namen:

  • Der Methodenname wird angefügt.

  • Wenn der Methodenname eine explizite Schnittstellenimplementierung ist, werden die Punkte entfernt.

  • Wenn die Methode generisch ist, wird Of angefügt, wobei n die Anzahl der generischen Methodenargumente ist.

    Spezielle Methodennamen wie Eigenschaften-Getter oder Setter werden wie in der folgenden Tabelle beschrieben behandelt:

Wenn die Methode lautet... Example Angefügter Methodenname
Ein Konstruktor .ctor Constructor
Ein statischer Konstruktor .cctor StaticConstructor
Ein Accessor mit Methodenname, der aus zwei Teilen besteht, die durch "_" getrennt sind (z. B. Eigenschaften-Getters) kind_name (gängiger Fall, aber nicht durch ECMA erzwungen) NameKind, wobei beide Teile großgeschrieben und getauscht wurden
Getter der Eigenschaft Prop PropGet
Setter der Eigenschaft Prop PropSet
Ereignishinzufüger Add
Ereignisentferner Remove
Ein Operator , der aus zwei Teilen besteht op_name NameOp
Beispiel: + Operator op_Add AddOp
Bei einem Konvertierungsoperator wird der Rückgabetyp angefügt. T op_Implicit ImplicitOpT

Hinweis

  • Getters und Setter von Indexern werden ähnlich wie die Eigenschaften behandelt. Der Standardname für einen Indexer lautet Item.
  • Parametertypnamen werden transformiert und verkettet.
  • Der Rückgabetyp wird ignoriert, es sei denn, es gibt eine Mehrdeutigkeit. Wenn es eine Überladungsdeutigkeit gibt, wird der Rückgabetyp am Ende des Namens angefügt.

Benennungskonventionen für Parametertypen

Gegeben Angefügte Zeichenfolge ist...
Ein TypT T

Der Namespace, die geschachtelte Struktur und generische Tics werden verworfen.
Ein Ausgabeparameterout T TOut
Ein Verweisparameterref T TRef
Ein ArraytypT[] TArray
Ein mehrdimensionaler ArraytypT[ , , ] T3
ZeigertypT* TPtr
Ein generischer TypT<R1, ...> TOfR1
Ein generisches Typargument!i vom Typ C<TType> Ti
Ein generisches Methodenargument!!i der Methode M<MMethod> Mi
Ein geschachtelter TypN.T N wird angefügt, dann T

Rekursive Regeln

Die folgenden Regeln werden rekursiv angewendet:

  • Da Fakes die Fakes-Assemblys mit C# generiert, wird jedes Zeichen, das ein ungültiges C#-Token erzeugen würde, zu "_" (Unterstrich) umgewandelt.

  • Wenn ein resultierender Name mit einem Element des deklarierenden Typs kollidiert, wird ein Nummerierungsschema verwendet, indem ein zweistelliger Zähler angefügt wird, beginnend mit 01.

Verwenden von Microsoft-Fälschungen in fortlaufender Integration

Erstellung von Microsoft Fakes-Assemblys

Microsoft Fakes ist ein Feature, das exklusiv in Visual Studio Enterprise verfügbar ist. Daher erfordert die Generation von Fakes Assemblies die Verwendung der Visual Studio Build Task beim Erstellen Ihres Projekts.

Hinweis

Eine alternative Strategie besteht darin, Ihre Fakes Assemblies direkt im Ci-System (Continuous Integration) zu überprüfen und die MSBuild-Aufgabe zu nutzen. Wenn Sie sich für diesen Ansatz entscheiden, müssen Sie sicherstellen, dass Sie einen Assemblyverweis auf die generierte Fakes-Assembly in Ihr Testprojekt einschließen, wie im folgenden Codeausschnitt gezeigt:

<Project Sdk="Microsoft.NET.Sdk">
    <ItemGroup>
        <Reference Include="FakesAssemblies\System.Fakes.dll"/>
    </ItemGroup>
</Project>

Dieser Verweis muss manuell hinzugefügt werden, insbesondere für SDK-Formatprojekte (d. h. .NET Core, .NET 5+ und .NET Framework), da diese Projekte jetzt implizit Assemblyverweise hinzufügen. Wenn Sie sich für diese Methode entscheiden, sollten Sie die Assembly "Fakes" aktualisieren, sobald sich die übergeordnete Assembly ändert.