2012-07-17 142 views
21

我想爲下面的類寫單元測試。
如果名稱不是「MyEntity」,那麼mgr應該是空白的。
負單元測試
使用管理器專用訪問器我想將名稱更改爲「Test」,以便mgr應該爲空。 然後將驗證mgr值。 要做到這一點,我想明確地調用靜態構造函數 但是當我打電話使用顯式調用靜態構造函數

Manager_Accessor.name = "Test" 
typeof(Manager).TypeInitializer.Invoke(null, null); 

的名字總是被設置爲「myEntity所」如何設置名稱爲「測試」並調用靜態構造函數靜態構造函數。

public class Manager 
{   
     private static string name= "MyEntity"; 

     private static object mgr; 

     static Manager() 
     { 
      try 
      { 
       mgr = CreateMgr(name); 
      } 
      catch (Exception ex) 
      { 
       mgr=null; 
      } 
     } 
} 
+2

把它製作「經理」靜態意味着*所有*「經理」實例共享相同的* *「的代碼mgr'值,這也是永遠不會被改變的(因爲它是隻讀的)。那真的是你想要的嗎? – 2012-07-17 10:46:59

+3

所以你需要改變一個私人的硬編碼靜態值,負責設置一個私有靜態只讀值用於測試目的?這就是爲什麼大多數可測試性的設計選擇都不喜歡靜態。 – 2012-07-17 10:56:13

回答

27

正如我今天發現,靜態構造函數,可直接調用:

another Stackoverflow post

其他的答案是優秀的,但如果你需要強制的一類 構造函數可以使用:

Type type = ...; 
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle); 

我不得不將此代碼添加到我的應用程序to work around a possible bug in the .net 4.0 CLR

4

如果您的類中有靜態成員(必須存在,否則靜態構造函數不會做太多),則不需要顯式調用靜態構造函數。

只需訪問您希望調用其靜態構造函數的類。 例如: -

public void MainMethod() 
{ 
    // Here you would like to call the static constructor 

    // The first access to the class forces the static constructor to be called. 
    object temp1 = MyStaticClass.AnyField; 

    // or 
    object temp2 = MyClass.AnyStaticField; 
} 
2

對於任何人發現這個線程,不知道......我只是做了測試。看起來System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor()只會運行靜態構造函數,如果它有而不是已由於其他原因而運行。

例如,如果您的代碼不正確,無論先前的代碼是否可能訪問了類並觸發了要運行的靜態構造函數,則無關緊要。以前的訪問會觸發靜態構造函數運行,但RunClassConstructor()也不會運行它。 RunClassConstructor()只運行靜態構造函數,如果它尚未運行。

RunClassConstructor()也訪問類而不是導致第二次運行靜態構造函數。

這是基於Win10 UWP應用程序中的測試。

+0

這讓我非常傷心,因爲現在每當我想重置我的靜態類的值時,我需要調用它的構造函數完全相同的靜態方法 - 設置默認值。 – 2018-02-28 12:46:13

+0

正確。你不是再次「構建」對象。只設置它們的值。假設你已經構建了一個非靜態對象,並在代碼中的一堆不同的地方存儲了對它的引用。現在你想重置對象的值。你不會重新構造(「新」)對象。所有那些舊的存儲引用仍然是舊對象。相反,你會有一個方法來重置已經構建的對象上的值。然後你會意識到構造函數和重置方法在做同樣的事情,所以你只需從構造函數調用reset方法。 – kburgoyne 2018-03-01 15:37:39

0

把你想在構造函數中調用到一個公共方法,並從構造