共用方式為


Microsoft Fakes 中的程式碼產生、編譯和命名約定

本文討論 Fakes 程式碼產生和編譯中的選項和問題,並說明 Fakes 產生的類型、成員和參數的命名慣例。

要求

  • Visual Studio Enterprise

  • .NET Framework 專案

  • .NET Core、.NET 5.0 或更新版本,以及 SDK 樣式專案支援已在 Visual Studio 2019 Update 6 中預覽,並在 Update 8 中預設啟用。 如需詳細資訊,請參閱 Microsoft Fakes for .NET Core 和 SDK 樣式專案

程式碼產生與編譯

設定程式碼生成的存根

存根類型的產生是在副檔名為 .fakes 的 XML 檔案中配置的。 Fakes 架構會透過自訂 MSBuild 工作整合到建置程式中,並在建置階段偵測這些檔案。 Fakes 程式碼產生器會將存根類型編譯成元件,並將參考新增至專案。

下列範例說明 FileSystem.dll中定義的存根類型:

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

類型篩選

可以在 .fakes 檔案中設定過濾器,以限制哪些類型應該存根。 您可以在 StubGeneration 元素下新增無限數目的 Clear、Add、Remove 元素,以建置所選類型的清單。

例如,下列 .fakes 檔案會針對 System 和 System.IO 命名空間下的類型產生存根,但排除 System 中包含 「Handle」 的任何類型:

<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>

篩選字串會使用簡單的文法來定義應如何進行比對:

  • 篩選器預設不區分大小寫;篩選器會執行子字串比對:

    el 匹配“hello”

  • ! 新增至篩選器的結尾,使其成為精確區分大小寫的比對:

    el! 與「hello」不匹配

    hello! 匹配"你好"

  • 在過濾器的結尾增添 * 會使其匹配字串的前綴:

    el* 與「hello」不匹配

    he* 匹配「hello」

  • 以分號分隔的清單中的多個篩選器會合併為分離:

    el;wo 匹配「hello」和「world」

模擬具體類別和虛擬方法

依預設,會針對所有非密封類別產生 Stub 類型。 可以透過 .fakes 設定檔將存根類型限制為抽象類別:

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

內部類型

Fakes 程式碼產生器會針對產生的 Fakes 元件可見的類型產生填充碼類型和存根類型。 若要讓 Fakes 和測試組件可見填補組件的內部類型,請將InternalsVisibleToAttribute屬性新增至填補組件程式碼中,以使所產生的 Fakes 組件和測試組件可見。 以下為範例:

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

強式命名元件中的內部類型

如果墊片組件的名稱很強,而且您想要存取組件的內部類型:

  • 您的測試組件和 Fakes 組件都必須進行強式命名。

  • 將測試和 Fakes 元件的公開金鑰新增至填充元件中的 InternalsVisibleToAttribute 屬性。 以下是填充的組件程式碼中的範例屬性在填充組件具有強式名稱時的外觀:

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

如果填充組件的名稱很強,則 Fakes 架構會自動對產生的 Fakes 組件進行強式簽署。 您必須在測試組件上進行強力簽名。 請參閱 Strong-Named 程序集

Fakes 架構會使用相同的索引鍵來簽署所有產生的元件,因此您可以使用此程式碼片段作為起點,將 fakes 元件的 InternalsVisibleTo 屬性新增至填充套件程式碼。

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

您可以指定包含替代索引鍵KeyFile 檔案的完整路徑作為 Fakes 檔案元素中的\Compilation屬性值,為 Fakes 元件指定不同的公開金鑰,例如您為填充組件建立的金鑰。 例如:

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

然後,您必須使用替代 .snk 檔案的公開金鑰,作為在插入的組件程式碼中,對應 Fakes 組件的 InternalVisibleTo 屬性的第二個參數:

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

在上述範例中,值 Alternate_public_keyTest_assembly_public_key 可以相同。

最佳化建置時間

Fakes 程序集的編譯可以顯著增加您的編譯時間。 您可以在一個中央專案中為 .NET 系統元件和第三方元件產生 Fakes 元件,以最大限度地減少建置時間。 因為這類元件很少在您的電腦上變更,所以您可以在其他專案中重複使用產生的 Fakes 元件。

從您的單元測試專案中,新增已編譯 Fakes 元件的參考,這些元件會放置在專案資料夾中的 FakesAssemblies 底下。

  1. 使用符合您測試專案的 .NET 執行階段版本建立新的類別程式庫。 我們稱之為 Fakes.Prebuild。 從專案中移除 class1.cs 檔案,不需要。

  2. 新增對您需要使用 Fakes 框架的所有系統和第三方組件的引用。

  3. 為每個元件新增 .fakes 檔案並建置。

  4. 從您的測試專案

    • 請確定您已經引用 Fakes 執行階段的 DLL:

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

    • 針對您已建立 Fakes 的每個組件,在專案的 Fakes.Prebuild\FakesAssemblies 資料夾中新增相應 DLL 檔案的參考。

避免組件名稱衝突

在小組組建環境中,所有組建輸出都會合併到單一目錄中。 如果多個專案使用 Fakes,不同版本的 Fakes 程式集可能會互相覆寫。 例如,TestProject1 偽造來自 .NET Framework 2.0 的 mscorlib.dll,而 TestProject2 偽造來自 .NET Framework 4 的 mscorlib.dll,都會生成 mscorlib.Fakes.dll Fakes 元件。

為了避免此問題,Fakes 應該在新增 .fakes 檔案時,自動為非專案參考建立版本限定的 Fakes 元件名稱。 當您建立 Fakes 元件名稱時,版本限定的 Fakes 元件名稱會內嵌版本號碼:

給定元件 MyAssembly 和版本 1.2.3.4,Fakes 元件名稱為 MyAssembly.1.2.3.4.Fakes。

您可以透過編輯 .fakes 中 Assembly 元素的 Version 屬性來變更或移除此版本:

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

假命名約定

填充碼類型和存根類型命名慣例

Namespaces

  • .Fakes 後綴會新增至命名空間。

    例如,System.Fakes 命名空間包含 System 命名空間的過渡類型。

  • Global.Fakes 包含空白命名空間的填充碼類型。

    類型名稱

  • Shim 前置詞會新增至類型名稱的開頭,以構建 Shim 類型名稱。

    例如,ShimExample 是 Example 類型的 shim 類型。

  • 存根前置詞會新增至類型名稱,以建置存根類型名稱。

    例如,StubIExample 是 IExample 類型的存根類型。

    類型引數和巢狀類型結構

  • 會複製泛型類型引數。

  • 巢狀類型結構會複製於嵌補類型。

擋板委派屬性或存根委派欄位命名法則

欄位命名的基本規則,從空名稱開始:

  • 方法名稱被附加。

  • 如果方法名稱是明確的介面實作,則會移除點。

  • 如果方法是泛型Of,則會附加 n,其中 n 是泛型方法引數的數目。

    特殊方法名稱 (例如屬性 getter 或 setter) 會如下表所述:

如果方法是... Example 已附加方法名稱
建構函式 .ctor Constructor
靜態 建構函式 .cctor StaticConstructor
方法名稱由兩部分組成的存取子,各部分以 "_" 分隔(例如屬性取得方法) kind_name (常見情況,但不由 ECMA 強制執行) NameKind,其中兩個部分都已大寫並交換
財產的獲取者 Prop PropGet
屬性設置器 Prop PropSet
事件添加器 Add
事件移除器 Remove
由兩個部分組成的運算子 op_name NameOp
例如:+ 運算子 op_Add AddOp
對於 轉換運算子,會附加傳回類型。 T op_Implicit ImplicitOpT

備註

  • 索引子的 getter 和 setter 的處理方式與屬性類似。 索引子的預設名稱是 Item
  • 參數類型 名稱會轉換並串連。
  • 除非存在多載不確定性,否則會忽略傳回類型。 如果發生多載的歧義時,傳回類型會附加在名稱的結尾。

參數類型命名慣例

假設 附加的字串是...
一種 類型T T

命名空間、巢狀結構和泛型 tics 會遭到捨棄。
輸出參數out T TOut
ref 參數ref T TRef
陣列類型T[] TArray
多維陣列類型T[ , , ] T3
指標類型T* TPtr
泛型類型T<R1, ...> TOfR1
類別的泛型引數!iC<TType> Ti
method 的泛型方法參數!!iM<MMethod> Mi
巢狀類型N.T N 附加,則 T

遞迴規則

下列規則會遞迴套用:

  • 因為 Fakes 使用 C# 來產生 Fakes 元件,所以任何會產生無效 C# 標記的字元都會轉換為 "_"(底線)。

  • 如果產生的名稱與宣告類型的任何成員衝突,則會透過附加從 01 開始的兩位數計數器來使用編號配置。

在持續整合中利用 Microsoft Fakes

Microsoft 假裝組件生成

Microsoft Fakes 是 Visual Studio Enterprise 中獨有的功能。 因此,在建置專案時,要產生 Fakes 元件,必須使用 Visual Studio 建置工作

備註

另一種策略是將您的 Fakes Assemblies 直接提交到持續整合(CI)系統中,並利用MSBuild 任務。 如果您選擇這種方法,則需要確保在測試專案中包含對產生的 Fakes 元件的元件參考,如下列程式碼片段所示:

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

必須手動新增此參考,特別是針對 SDK 樣式專案 (即 .NET Core、.NET 5+ 和 .NET Framework),因為這些專案現在會隱含地新增元件參考。 如果您決定使用此方法,請務必在父元件發生變更時更新 Fakes 元件。