Java 测试工厂行为

Java 测试工厂行为,java,unit-testing,factory-pattern,Java,Unit Testing,Factory Pattern,我想知道测试工厂行为代码的最佳实践是什么。在我的例子中,工厂创建了一些依赖实例,这些依赖实例将传递给FooBar实例的构造函数 public class FooBarFactory { private Dependency1 dependency1; private Dependency2Factory factory; public FooBarFactory(Dependency1 dependency1, Dependency2Factory factory) { t

我想知道测试工厂行为代码的最佳实践是什么。在我的例子中,工厂创建了一些依赖实例,这些依赖实例将传递给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让我有点烦恼,因为这会破坏封装。我也可以使用反射来检索字段值,但是我通常认为这是坏的做法,因为它很容易被破解。
任何人都可以提供关于这个问题的见解?

作为单元测试,您应该测试您的单元(类)和它

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

Dependency2Factory
应在单独的单元测试中进行测试


您不需要测试方法
List.get(int index)
是否在每次在实现中使用列表时都有效,对吗?

我想我想到的建议是反过来注入FooBarFactory的依赖项,因此,它将Dependency1和Dependency2Factory作为构造函数参数或setter方法中的值。

模拟如何?模拟运行测试代码段所需的每个依赖项。
有一些很好的模拟框架,比如mockito。

一个解决方案是模拟
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()); }};
    }
}

让我困惑的是一句话
为了测试工厂行为,我现在要做的是在FooBar中创建一些受保护的getter
。您不必使用
FooBar
来测试工厂行为。如果我不能使用FooBar(这是工厂调用的结果),我如何测试FooBar是否已正确构建?您应该通过注入定制的测试依赖项来测试
FooBar
,然后在单独的测试中测试您的工厂是否生成了您期望的结果。不要把这两个测试混在一起。我不是想把这两个测试混在一起。我试图测试的只是工厂是否正确创建了FooBar实例。为此,我必须测试FooBarFactory的构建行为,它生成一个FooBar实例。因此,工厂的结果在FooBar实例中。我知道我需要分离测试关注点,在这种情况下,我信任Dependency2Factory结果。我想测试的是,工厂返回的实例实际上被注入到FooBar中,这是工厂的行为(调用工厂并将实例传递给FooBar)但是在FooBarFactory中,您能够配置Dependency2Factory吗?因此您可以只注入一个模拟来创建您期望的对象,并在FooBar(已创建的对象)上测试执行需要创建bean的内容,如果没有出现空指针,并且使用了模拟工厂,那么它也在工作,但我不确定这是否会影响功能测试,因为需要了解FooBar才能知道如何触发NPE。是的,这是真的,但由于
FooBar
的创建依赖于此,我看不出问题,您正在测试对象在
FooBar
实例上的配置是否正确。这比每个反射更好,因为您需要确切地知道字段名…;)