我有一个不可变类,其中包含一些在构造函数执行期间设置的私有字段。我想对这个构造函数进行单元测试,但在这种情况下我不确定“最佳实践”。
简单示例
此类在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?
}
}
编辑1 :我已经用一个潜在的解决方案回答了这个问题,但我不确定这是否是“正确的方法”。因此,如果您认为自己有更好的想法,请发布。
这个例子不值得测试,但假设构造函数有一些更复杂的逻辑。这是避免测试构造函数的最佳方法,并假设它适用于类的方法的所有测试都有效吗?
编辑2 :看起来我做的样本有点简单。我已经用更合理的情况更新了它。
答案 0 :(得分:8)
没有,除非你使用那个领域。您不希望通过测试进行过度规范。换句话说,没有必要测试赋值运算符的工作原理。
如果您在某个方法或某个方法中使用该字段,请调用该方法并对其进行断言。
编辑:
假设构造函数有一些更复杂的逻辑
你不应该在构造函数中执行任何逻辑。
编辑2:
public Class2Test() { _StringProperty = ConfigurationManager.AppSettings["stringProperty"]; }
不要那样做! =)您的简单单元测试现在已成为集成测试,因为它取决于多个类的成功操作。编写一个处理配置值的类。 WebConfigSettingsReader可以是名称,它应该封装ConfigurationManager.AppSettings
调用。将该SettingsReader类的实例传递给Class2Test
的构造函数。然后,在您的单元测试中,您可以模拟您的WebConfigSettingsReader
,并对您可能对其进行的任何调用存根响应。
答案 1 :(得分: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
内部财产的目的时,不清楚(没有评论)。
非常感谢其他想法。
答案 2 :(得分:1)
在编辑中,您现在依赖于难以测试的ConfigurationManager。
一个建议是提取一个接口,然后使Class2Test ctor将IConfigManager实例作为参数。现在你可以使用假/模拟对象来设置它的状态,这样就可以测试依赖于Configuration的任何方法,看看它们是否使用了正确的值......
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());
}
}