2011-07-01 37 views
1

我一直有一個問題,痣類型不工作在靜態構造函數。我已經創建了兩個簡單的例子來說明這個問題:痣不能在靜態構造函數中工作

我有一個簡單的實例類如下:

public class InstanceTestReader 
{ 
    public InstanceTestReader() 
    { 
     IFileSystem fileSystem = new FileSystem(); 

     this.Content = fileSystem.ReadAllText("test.txt"); 
    } 

    public string Content { get; private set; } 
} 

我有一個單元測試的具體步驟如下:

[TestMethod] 
    [HostType("Moles")] 
    public void CheckValidFileInstance_WithMoles() 
    { 
     // Arrange 
     string expectedFileName = "test.txt"; 
     string content = "test text content"; 

     Implementation.Moles.MFileSystem.AllInstances.ReadAllTextString = (moledTarget, suppliedFilename) => 
     { 
      Assert.AreEqual(suppliedFilename, expectedFileName, "The filename was incorrect"); 
      return content; 
     }; 

     // Act 
     string result = new InstanceTestReader().Content; 

     // Assert 
     Assert.AreEqual(content, result, "The result was incorrect"); 
    } 

該作品沒有問題。

如果我改變我的呼喚類是靜態但(不是Moled類,但調用的類),痣不再有效:

public static class StaticTestReader 
{ 
    static StaticTestReader() 
    { 
     IFileSystem fileSystem = new FileSystem(); 

     Content = fileSystem.ReadAllText("test.txt"); 
    } 

    public static string Content { get; private set; } 
} 

,並相應修改我的單元測試:

[TestMethod] 
    [HostType("Moles")] 
    public void CheckValidFileStatic_WithMoles() 
    { 
     // Arrange 
     string expectedFileName = "test.txt"; 
     string content = "test text content"; 

     Implementation.Moles.MFileSystem.AllInstances.ReadAllTextString = (moledTarget, suppliedFilename) => 
     { 
      Assert.AreEqual(suppliedFilename, expectedFileName, "The filename was incorrect"); 
      return content; 
     }; 

     // Act 
     string result = StaticTestReader.Content; 

     // Assert 
     Assert.AreEqual(content, result, "The result was incorrect"); 
    } 

...現在痣不再有效。運行此測試時,出現錯誤「無法找到文件」d:\ blah \ blah \ test.txt'「。我得到這個是因爲Moles不再負責我的FileSystem類,所以單元測試正在調用正在文件系統上尋找文件的原始實現。

所以,唯一的變化就是Moled方法被調用的類現在是靜態的。我沒有更改Moled類或方法,它們仍然是實例類型,所以我不能使用Implementation.Moles.SFileSystem 語法,因爲這將用於模擬靜態類。

請有人可以幫助解釋如何讓痣在靜態方法/構造函數中工作?

非常感謝!

回答

4

靜態構造函數與靜態方法不同。通過一種方法,您可以控制其何時何地被調用。在執行任何對類的訪問之前,構造函數會被運行時自動調用,在這種情況下會導致構造函數在設置FileSystem的痣之前被調用,從而導致出現錯誤。

如果你改變你的實現類似於下面的東西,那麼它應該工作。

public static class StaticTestReader 
{ 
    private static string content; 

    public static string Content 
    { 
     get 
     { 
      if (content == null) 
      { 
       IFileSystem fileSystem = new FileSystem(); 

       content = fileSystem.ReadAllText("test.txt"); 
      } 

      return content; 
     } 
    } 
} 


更新:

但是,如果你不能改變你的實現是痣提供唯一的其他選擇是爲你避免被執行的靜態構造函數的代碼,然後痣Content直接屬性。要刪除一個靜態構造函數,你需要包含以下組件級屬性在您的測試程序集的類型:

[assembly: MolesEraseStaticConstructor(typeof(StaticTestReader))] 
+0

+1寫得很好的解釋! – TheSilverBullet

0

我認爲你必須從你的聲明中刪除AllInstances。要訪問靜態,你不需要一個類的實例。

試試這個:

Implementation.Moles.MFileSystem.ReadAllTextString = (...)