【问题标题】:How to test constructor of a class that has a @PostConstruct method using Spring?如何使用 Spring 测试具有 @PostConstruct 方法的类的构造函数?
【发布时间】:2012-05-17 19:06:00
【问题描述】:

如果我有一个带有@PostConstruct 方法的类,我如何使用JUnit 和Spring 测试它的构造函数以及它的@PostConstruct 方法?我不能简单地使用 new ClassName(param, param) 因为它没有使用 Spring——@PostConstruct 方法没有被触发。

我在这里遗漏了什么明显的东西吗?

public class Connection {
    private String x1;
    private String x2;

    public Connection(String x1, String x2) {
        this.x1 = x1;
        this.x2 = x2;
    }

    @PostConstruct
    public void init() {
        x1 = "arf arf arf";
    }

}


@Test
public void test() {
    Connection c = new Connection("dog", "ruff");
    assertEquals("arf arf arf", c.getX1());
}

我有一些类似的东西(虽然稍微复杂一点),但 @PostConstruct 方法没有受到影响。

【问题讨论】:

    标签: java spring unit-testing junit postconstruct


    【解决方案1】:

    @PostConstruct 必须改变对象的状态。因此,在 JUnit 测试用例中,获取 bean 后检查对象的状态。如果与@PostConstruct设置的状态相同,则测试成功。

    【讨论】:

    • 问题不在于如何测试它是否已更改,而在于 @PostConstruct 没有被解雇。我将编辑我的帖子以使其更清楚。
    【解决方案2】:

    看看Spring JUnit Runner

    你需要在你的测试类中注入你的类,这样 spring 就会构造你的类,并且还会调用 post 构造方法。参考宠物诊所的例子。

    例如:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:your-test-context-xml.xml")
    public class SpringJunitTests {
    
        @Autowired
        private Connection c;
    
        @Test
        public void tests() {
            assertEquals("arf arf arf", c.getX1();
        }
    
        // ...
    

    【讨论】:

    • 我明白这一点,正如我所说。但是如何在一个测试类中测试这个构造函数的多个排列呢?我的问题有什么不清楚的地方?
    • 我想要这个类的构造函数的五个测试用例。真的没有比拥有五个这样的 bean 的应用程序上下文并加载它更好的方法了吗?
    • 实时如果有 5 种可能的方式来注入你的类,那么恐怕在这种情况下你必须创建 5 个 bean 定义。
    • 我将通过在对象上调用 @PostConstruct 方法来测试它。
    【解决方案3】:

    默认情况下,Spring 不会意识到 @PostConstruct 和 @PreDestroy 注解。要启用它,您必须注册“CommonAnnotationBeanPostProcessor”或在 bean 配置文件中指定“”。

    <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />

    <context:annotation-config />

    【讨论】:

      【解决方案4】:

      如果Connection 的唯一容器管理部分是您的@PostContruct 方法,则只需在测试方法中手动调用它:

      @Test
      public void test() {
        Connection c = new Connection("dog", "ruff");
        c.init();
        assertEquals("arf arf arf", c.getX1());
      }
      

      如果还有更多,例如依赖项等,您仍然可以手动注入它们,或者 - 正如 Sridhar 所说 - 使用 spring 测试框架。

      【讨论】:

      • 这就是我最终所做的。
      • 初始化可以是私有的
      • @shanyangqu 然后你可以使用 ReflectionTestUtils 或者类似的东西。毕竟是测试代码。
      • @mrembisz 我知道,只是觉得它值得一提......我还发现 deencapsulate 更强大......thean ReflectionTestUtils
      • @AHungerArtist 这应该添加到接受的答案中。我不想让整个 SpringJUnit4Runner 类给我的测试带来负担,并且简单地调用该方法似乎工作得很好。此答案适用于测试人员想要测试目标类而不担心弹簧上下文的情况。
      猜你喜欢
      • 2018-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-27
      相关资源
      最近更新 更多