所以我有一个工厂类,我试图找出单元测试应该做的事情。 从这个问题,我可以确认返回的接口是我希望一个特定的具体类型。
我应该怎么检查如果将工厂返回的具体类型(因为没有必要 - 此刻 - 对接口使用)? 目前我正在做类似如下:
[Test]
public void CreateSomeClassWithDependencies()
{
// m_factory is instantiated in the SetUp method
var someClass = m_factory.CreateSomeClassWithDependencies();
Assert.IsNotNull(someClass);
}
这里的问题是, Assert.IsNotNull
似乎有些多余。
另外,我的工厂方法可能会建立像这样特定类的依赖关系:
public SomeClass CreateSomeClassWithDependencies()
{
return new SomeClass(CreateADependency(), CreateAnotherDependency(),
CreateAThirdDependency());
}
我想确保我的工厂方法正确设置所有这些依赖。 难道就没有别的办法做到这一点,然后使这些依赖public/internal
性质,然后我在单元测试检查? (我不修改测试对象,以满足测试的大风扇)
编辑:在回答罗伯特·哈维的问题,我使用NUnit作为我的单元测试框架(但我不会想到它会做出太大的差别)
通常情况下,有什么不妥创建可用于基于状态检测的公共属性。 是的:这是你创建的,以使测试场景代码,但它伤了你的API? 它是可以想象其他客户端将稍后发现有用相同的属性?
有测试代码和测试驱动设计之间的细线。 我们不应该引入有没有其他潜在的,而不是满足测试要求的代码,但它是相当好的介绍是遵循公认的设计原则,新的代码。 我们让测试推动我们的设计-这就是为什么我们把它称为TDD :)
添加一个或多个属性的一类给用户检查那类,在我看来,往往是一个合理的事情做的更好的可能性,所以我不认为你应该解雇引入这样的属性。
除此之外,我第二纳德的答案:)
如果工厂正在恢复的具体类型,和你保证,你的工厂总是返回一个具体类型,并且不为空,则没有,没有测试太多价值。 它可以让你确保,在这种预期不受侵犯的时候,事情就是这样的异常没有抛出。
测试的这种风格简单地确保了,当你在将来的变化,你的工厂的行为不会改变而不让你知道。
如果你的语言支持它,为你的依赖,你可以使用反射。 这并不总是最简单的维护,将你的测试非常严格,以您的实现。 你必须决定,如果这是可以接受的。 这种方法往往是非常脆。
但你真的似乎试图分开哪些类构造,从构造函数的调用方式。 你可能只是与使用DI框架来获得这种灵活性更好。
通过new
,你需要他们-ing你所有的类型,你不给自己很多的接缝(接缝是在那里你可以改变你的程序的行为,而不在那个地方编辑的地方)的工作。
随着例子,你给它虽然,你可以从工厂派生类。 然后覆盖/模拟CreateADependency()
CreateAnotherDependency()
和CreateAThirdDependency()
现在,当你调用CreateSomeClassWithDependencies()
你能感知是否创建正确的依赖关系。
注:“缝”的定义来自迈克尔羽毛的书,“修改代码的工作”。 它包含了许多技术的例子可测性增加未测试的代码。 您可能会发现它非常有用。
我们做的是创建一个工厂的依赖关系,以及我们使用扶养注入框架运行测试时代替模拟工厂为以假乱真。 然后,我们建立这些模拟工厂适当的期望。
您可以随时使用的东西反射。 有没有必要暴露的东西只是单元测试。 我觉得很罕见,我需要用反射来达到,它可能是糟糕的设计标志。
看你的示例代码,是断言不为空似乎是多余的,这取决于你设计你的工厂的路上,有些人会从工厂返回null对象,而不是exceptioning出来。
据我了解,你要测试的依赖关系是否正确构建并传递到新的实例?
如果我不能使用像谷歌吉斯的框架,我可能会做这样的事情(在这里使用JMock的和Hamcrest):
@Test
public void CreateSomeClassWithDependencies()
{
dependencyFactory = context.mock(DependencyFactory.class);
classAFactory = context.mock(ClassAFactory.class);
myDependency0 = context.mock(MyDependency0.class);
myDependency1 = context.mock(MyDependency1.class);
myDependency2 = context.mock(MyDependency2.class);
myClassA = context.mock(ClassA.class);
context.checking(new Expectations(){{
oneOf(dependencyFactory).createDependency0(); will(returnValue(myDependency0));
oneOf(dependencyFactory).createDependency1(); will(returnValue(myDependency1));
oneOf(dependencyFactory).createDependency2(); will(returnValue(myDependency2));
oneOf(classAFactory).createClassA(myDependency0, myDependency1, myDependency2);
will(returnValue(myClassA));
}});
builder = new ClassABuilder(dependencyFactory, classAFactory);
assertThat(builder.make(), equalTo(myClassA));
}
(如果你不能嘲笑ClassA的,你可以到myClassA使用新分配非模拟版)