2008-09-25 63 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()); 
     } 
    } 
相关问题