2008-09-25 85 views
1

我有一個不可變的類,在構造函數執行期間設置了一些私有字段。我想單元測試這個構造函數,但我不確定這種情況下的「最佳實踐」。如何單元測試不可變類的構造函數?

簡單示例

該類在Assembly1定義:

public class Class2Test 
{ 
    private readonly string _StringProperty; 

    public Class2Test() 
    { 
     _StringProperty = ConfigurationManager.AppSettings["stringProperty"]; 
    } 
} 

該類在Assembly2定義:

[TestClass] 
public class TestClass 
{ 
    [TestMethod] 
    public void Class2Test_Default_Constructor() 
    { 
     Class2Test x = new Class2Test(); 
     //what do I assert to validate that the field was set properly? 
    } 
} 

EDIT 1:我已經回答了這個問題有可能的解決方案,但我不確定這是否是「正確的路線」。所以如果你認爲你有更好的主意,請發佈它。

這個例子並不值得測試,但假設構造函數有一些更復雜的邏輯。避免測試構造函數並假設它在所有類上的方法測試都能正常工作的情況下才是最好的方法?

編輯2:看起來我讓樣品有點簡單。我用更合理的情況更新了它。

+0

的代碼看,我可以在那裏找不到可能失敗的聲明。我沒有看到任何需要測試的理由。 – jop 2008-09-25 00:18:17

+0

我更新了示例。假設構造函數中有些東西可能會失敗,我試圖測試的實際代碼非常冗長,我不想將它粘貼到此處。 – 2008-09-25 00:20:46

回答

8

什麼也沒有,除非您使用該字段。你不想通過測試過度規範。換句話說,不需要測試賦值操作符的工作原理。

如果您在某個方法或某個方法中使用該字段,請調用該方法並在該方法上聲明。

編輯:

假設構造函數

你不應該在執行任何構造邏輯一些更復雜的邏輯。

編輯2:

public Class2Test() 
{ 
    _StringProperty = ConfigurationManager.AppSettings["stringProperty"]; 
} 

不要那樣做! =)你的簡單單元測試現在已經成爲一個集成測試,因爲它取決於多個類的成功運行。編寫一個處理配置值的類。 WebConfigSettingsReader可以是名稱,它應該封裝ConfigurationManager.AppSettings調用。將該設置讀取器類的實例傳遞給構造函數Class2Test。然後,在你單元測試,你可以嘲笑你的WebConfigSettingsReader和存根出來你可能作出的任何呼叫的響應。

+0

+1您想要測試行爲,而不是實現。 – 2008-09-25 00:20:17

1

我已在Assembly1(代碼)上正確啓用[InternalsVisibleTo],以便與Assembly2(測試)存在信任關係。

public class Class2Test 
{ 
    private readonly string _StringProperty; 
    internal string StringProperty { get { return _StringProperty; } } 

    public Class2Test(string stringProperty) 
    { 
     _StringProperty = stringProperty; 
    } 
} 

,讓我堅持這一點:

Assert.AreEqual(x.StringProperty, "something"); 

我真的不喜歡這個唯一的一點是,它不是明確的(沒有評論)時,你只是在看Class2Test什麼內部財產的目的是。

更多的想法將不勝感激。

1

在你的編輯,你現在有一個ConfigurationManager中說扶養是很難測試。

一個建議是一個接口提取到它,然後使Class2Test構造函數採取IConfigManager實例作爲參數。現在你可以使用一個假的/模擬對象建立其狀態,使得依靠配置的任何方法可以進行測試,看看他們是否使用了正確的價值觀......

public interface IConfigManager 
    { 
     string FooSetting { get; set; } 
    } 

    public class Class2Test 
    { 
     private IConfigManager _config; 
     public Class2Test(IConfigManager configManager) 
     { 
      _config = configManager; 
     } 

     public void methodToTest() 
     { 
      //do something important with ConfigManager.FooSetting 
      var important = _config.FooSetting; 
      return important; 
     } 
    } 

    [TestClass] 
    public class When_doing_something_important 
    { 
     [TestMethod] 
     public void Should_use_configuration_values() 
     { 
      IConfigManager fake = new FakeConfigurationManager(); 
      //setup state 
      fake.FooSetting = "foo"; 
      var sut = new Class2Test(fake); 
      Assert.AreEqual("foo", sut.methodToTest()); 
     } 
    } 
相關問題