2012-07-09 84 views
0

我在想什么是测试工厂行为代码的最佳实践。在我的例子中,工厂创建了一些依赖实例,这些实例将被传递给FooBar实例的构造函数。测试工厂行为

public class FooBarFactory { 
    private Dependency1 dependency1; 
    private Dependency2Factory factory; 

    public FooBarFactory(Dependency1 dependency1, Dependency2Factory factory) { 
    this.dependency1 = dependency1; 
    this.factory = factory; 
 } 

    public FooBar create() { 
    return new FooBar(dependency1, factory.create(), new Dependency3()); 
    } 
} 

该依赖关系可以由其他一些工厂创建,或者可以由被测工厂直接创建。

为了测试工厂行为,我现在要做的是在FooBar中创建一些受保护的getter以检索依赖关系,以便我可以断言构造函数注入并正确创建依赖关系。

这是我不确定的地方。为了测试的目的添加一些getter让我有点困扰,因为它破坏了封装。我也可以使用反射来检索字段值,但我通常会考虑这种不好的做法,因为它很容易中断。

任何人都可以提供有关此问题的见解?

+0

什么让我困惑的是一句'要测试工厂的行为,我有什么对现在要做的是创造一些FooBar'保护干将。您不必使用'FooBar'来测试工厂行为。 – Keppil 2012-07-09 14:15:04

+0

如果我不能使用工厂调用的结果FooBar,我如何测试FooBar已经正确构建? – ebelanger 2012-07-09 14:19:19

+0

你应该通过注入定制的测试依赖项来测试'FooBar',然后在一个单独的测试测试中测试你的工厂产生的期望。不要混合两个测试。 – Keppil 2012-07-09 14:21:11

回答

0

作为一个单元测试,你应该测试你的单元(类),只是这个。

工厂内的工厂创建的值应在其单元测试中进行测试。例如在你的情况下,测试dependency2Factory返回的内容是没有意义的,因为为了FooBar工作,Dependency2Factory也应该工作(如果它不可配置),如果它是可配置的,你可以提供你自己的模拟和这就够了。

Dependency2Factory应在独立的单元测试中测试。

您不测试方法List.get(int index)是否每次在您的实施权利中使用列表时都有效?

+0

我明白我需要分离测试问题,在这种情况下,我确实信任Dependency2Factory结果。我想测试的是工厂返回的实例实际上注入到FooBar中,这是工厂的行为(调用工厂并将实例传递给FooBar) – ebelanger 2012-07-09 14:17:50

+0

但在FooBarFactory中,您是否可以配置Dependency2Factory? – 2012-07-09 14:20:14

+0

是的,我会更新代码。 – ebelanger 2012-07-09 14:21:36

0

我想到的想法是依次注入FooBarFactory的依赖关系,以便它将Dependency1和Dependency2Factory作为构造函数参数或setter方法中的值。

0

嘲笑怎么样?模拟运行测试代码所需的每个依赖项。 有几个很好的模拟框架,如mockito。

1

一种解决方案是模拟FooBar类,并验证构造函数的调用,通过该调用创建了由FooBarFactory#create()返回的实例。使用JMockit嘲讽的API,这样的测试看起来像:

public class FooBarFactoryTest 
{ 
    @Injectable Dependency1 dep1; 
    @Injectable Dependency2 dep2; 
    @Cascading @Injectable Dependency2Factory dep2Factory; 
    @Mocked FooBar mockFooBar; 
    @Tested factory; 

    @Test 
    public void createFooBarWithProperDependencies() 
    { 
     assertNotNull(factory.create()); 

     new Verifications() {{ new FooBar(dep1, dep2, (Dependency3) withNotNull()); }}; 
    } 
}