【发布时间】:2015-01-26 14:52:47
【问题描述】:
我已经为一个类编写了一个构造函数,并且我正在测试每个参数是否为空。请参见下面的示例:
public MyClass(IObjectA objA, IObjectB objB) : IMyClass
{
if (objA == null)
{
throw new ArgumentNullException("objA");
}
if (objB == null)
{
throw new ArgumentNullException("objB");
}
...
}
通常我通过模拟 IObjectA 和 IObjectB 并传入它们来对此进行单元测试(使用 Moq)。上面的示例将创建 2 个单元测试来测试每个场景。
我遇到的问题是第三个参数被传递到构造函数时。它要求我更改以前的测试,因为我突然得到“MyClass 的构造函数没有 2 个参数”类型异常。
我也使用 AutoMockContainer。本质上,我希望能够通过在容器中注册一个空对象来测试构造函数。例如:
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void ConstructionThrowsExceptionForNullObjA()
{
// Arrange.
var container = new AutoMockContainer(new MockRepository(MockBehavior.Default));
container.Register<IObjectA>(null);
// Act.
var sut = container.Create<MyClass>();
}
那么在构造函数中添加多少新参数并不重要。我不必更新我的单元测试。
很遗憾,上面的单元测试通过了。但是出于错误的原因。 Register<T>() 方法抛出 ArgumentNullException 而不是“Act”部分中执行的代码。
有没有人建议能够测试构造函数参数而不必在以后添加新参数时重新访问单元测试?
【问题讨论】:
-
如果你显式地测试构造函数,那么当你改变构造函数的契约时测试将不得不改变。任何被测功能也是如此。恐怕这就是生活。
-
您是否在应用程序中使用 IoC 容器将依赖项注入此类?如果是这样,请质疑编写(因此必须维护)许多测试您的基础设施的测试(可能是数百个)的价值。我研究的一个解决方案有数千个测试,所有测试都测试空 ctor 参数,维护起来简直就是一场噩梦。
-
@Matt 很遗憾,我的客户想要 100% 的测试覆盖率。我自己并不关心测试覆盖率统计数据,通常不会测试这些东西或接线。我喜欢防御性编程,但有时当我在试图实现 100% 覆盖率的地方工作时,我觉得我只是在为自己做事。