3

我以前使用过 Spring DI,我认为的好处之一是我可以在不涉及 Spring 的情况下测试我的 Spring bean 类(为简洁起见省略了导入):

public class Foo {
    private String field;

    public void setField(String field) { this.field = field; }
    public String getField() { return field; }
} 

public class TestFoo {
    @Test
    public void test_field_is_set() {
       Foo foo = new Foo();
       foo.setField("Bar");
       assertEquals("Bar", foo.getField());
    }
}

现在我正在试验 JSR-330,这意味着不显式编写 setter。

到目前为止,我一直在使用 Hk2,纯粹是因为一些关于 Jersey 与 Hk2 相关联的轶事,并且很难与其他 JSR-330 实现共存。

public class Foo {
   @Inject 
   private String field;
}

我有一半预计会发生一些神奇的事情,@Inject 注释导致设置器可用,但事实并非如此:

Foo foo = new Foo();
foo.setField("Bar"); // method setField(String) is undefined for the type Foo
  • 我如何(方便地)在不调用框架的情况下测试这种带注释的类?
  • 如果做不到这一点,我如何以可移植的方式调用框架(即,不将我的测试代码紧密耦合到 Hk2、Guice 等)
  • 如果做不到这一点,那么测试以这种方式注释的类的典型、干净的方法是什么?
4

4 回答 4

2

最简单的是将字段设置为包私有(而不是私有),然后在测试中直接设置它们。(如果测试在同一个包中,这有效)

public class Foo {
   @Inject 
   String field;
}



Foo foo = new Foo();
foo.field = "bar";

这具有避免反射的优点,因此重构是安全的。

于 2013-11-07T08:32:04.730 回答
1

你提到的字段注入方式其实就是典型的Spring风格;许多程序员根本不为私有注入字段编写设置器。Spring(带有@Autowiredor @Inject)和 JSR-330 容器通常使用直接字段反射而不是 setter 来注入字段。

正因为如此,如果您不想使用任何 DI 框架,您可以自己将必要的反射代码编写到您的单元测试中,但这似乎是为了避免测试依赖而过大;毕竟,使用的重点@Inject是您正在对接口进行编码,并且您不会避免使用 JVM 来避免与其耦合。

测试此类类的常用方法是为您喜欢的任何容器设置测试上下文,并在该上下文中运行单元测试。如果您使用 Spring,您将在您的目录(或等效目录)中放置一个applicationContext-test.xml文件或TestConfigsrc/test/,如果您使用 Guice,您将编写一个模块来连接模拟或测试数据集。

于 2013-11-05T13:16:04.710 回答
1

事实证明,依赖私有/受保护字段访问的框架并不少见。Hibernate、JPA、几个 JSR-330 实现,包括 Spring 本身,都这样做了。

Spring 的 spring-test 包提供了一个ReflectionTestUtils类,其中包含用于访问这些字段的静态方法。

使用这个可以测试问题中的类:

import static org.springframework.test.util.ReflectionTestUtils.*;

...

@Test
public void testUsingSpringReflectionTestUtils() {
    Foo foo = new Foo();
    setField(foo, "field", "Bar");
    assertEquals("Bar", foo.getField());
}

您需要在测试类路径中使用 spring-test 和 spring-core 才能使其正常工作,但它不会为您的生产代码添加对 Spring 的依赖。

(欢迎对相同原则的替代实现发表评论。鉴于 Spring 有一个很好的实现,我认为它不值得自己动手,不管它多么简单。)

于 2013-11-05T16:34:24.793 回答
1

试试“针”:http: //needle.spree.de/overview

needle 是一个仅模拟容器行为的 DI 测试框架,使单元测试变得非常简单。

于 2013-11-05T23:28:13.423 回答