我开发了一些具有类似行为的类,它们都实现了相同的接口。我实现了一个工厂,它创建适当的对象并返回接口。我正在为工厂写一个单元测试。你得到的只是对象的接口。 测试工厂工作正常的最佳方法是什么?
我想知道Java中的答案,但如果有一个跨越语言的解决方案,我想知道它。
答案中的第2号,会像其他答案那样完成吗?如果是这样,我将标记另一个接受的答案并重新提出我的问题,以解决返回界面的工厂以及您不知道哪种类型的具体类实现了界面,以及您知道具体类是什么的情况使用
答案 0 :(得分:25)
如果您测试返回的对象是否是特定具体类的实例,则不是单元测试。你是集成测试。虽然集成测试很重要,但它不是一回事。
在单元测试中,您只需要测试对象本身。如果断言返回的抽象对象的具体类型,那么您正在测试返回对象的实现。
当进行单元测试时,有四件事你想断言:
此外,您只想测试从对象实例(即公共接口)可以观察到的内容。否则,您将自己绑定到一组特定的实现细节。这将要求您在这些细节发生变化时更改测试。
对工厂的单元测试真的无趣,因为您对返回的查询对象的行为不感兴趣。这种行为(希望)可以在其他地方进行测试,也可以在对象本身进行单元测试时进行测试。您只对返回的对象是否具有正确的类型感兴趣,如果您的程序编译,则可以保证。
由于工厂不随时间而变化(因为那时它们将是“建筑商”,这是另一种模式),因此没有可测试的命令。
工厂负责实例化对象,因此他们不应该依赖其他工厂为他们做这件事。他们可能依赖于Builder,但即便如此,我们也不应该测试Builder的正确性,只测试Builder是否收到消息。
这意味着您必须在Factories上测试的是他们是否将消息发送到他们所依赖的对象。如果使用依赖注入,这几乎是微不足道的。只需在单元测试中模拟依赖项,并验证它们是否收到了消息。
就是这样。如果没有依赖关系,则无需测试。除了可能断言返回的对象不是null
引用。
如果您要求返回的抽象对象类型是特定具体类型的实例,那么这属于集成测试。
其他人已经使用instanceof
运算符解答了如何执行此操作。
答案 1 :(得分:18)
由于我不知道您的工厂方法如何,我现在可以建议的是
检查对象是否是您正在寻找的正确具体实现:
IMyInterface fromFactory = factory.create(...);
Assert.assertTrue(fromFactory instanceof MyInterfaceImpl1);
您可以检查工厂是否使用有效的实例变量设置具体实例。
答案 2 :(得分:0)
if (myNewObject instanceof CorrectClass)
{
/* pass test */
}
<强>更新强>
不知道为什么这会被标记下来,所以我会稍微扩展一下......
public void doTest()
{
MyInterface inst = MyFactory.createAppropriateObject();
if (! inst instanceof ExpectedConcreteClass)
{
/* FAIL */
}
}
答案 3 :(得分:0)
@ cem-catikkas我认为比较getClass()。getName()值会更正确。在MyInterfaceImpl1类是子类的情况下,您的测试可能会被破坏,因为子类是MyInterfaceImpl1的实例。我会改写如下:
IMyInterface fromFactory = factory.create(...);
Assert.assertEquals(fromFactory.getClass().getName(), MyInterfaceImpl1.class.getName());
如果您认为这可能会以某种方式失败(我无法想象),请进行两次验证。
答案 4 :(得分:0)
如果您的工厂返回了具体实例,则可以使用 @Parameters 批注以获得更灵活的自动单元测试。
package it.sorintlab.pxrm.proposition.model.factory.task;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collection;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import static org.junit.Assert.*;
@RunWith(Parameterized.class)
public class TaskFactoryTest {
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
{ "sas:wp|repe" , WorkPackageAvailabilityFactory.class},
{ "sas:wp|people", WorkPackagePeopleFactory.class},
{ "edu:wp|course", WorkPackageCourseFactory.class},
{ "edu:wp|module", WorkPackageModuleFactory.class},
{ "else", AttachmentTaskDetailFactory.class}
});
}
private String fInput;
private Class<? extends TaskFactory> fExpected;
public TaskFactoryTest(String input, Class<? extends TaskFactory> expected) {
this.fInput = input;
this.fExpected = expected;
}
@Test
public void getFactory() {
assertEquals(fExpected, TaskFactory.getFactory(fInput).getClass());
}
}
此示例是使用 Junit4 创建的。您会注意到,仅用一行代码就可以测试Factory方法的所有结果。