在单元测试中请求范围bean管理

时间:2012-04-17 15:23:11

标签: java spring unit-testing junit scope

在单元测试中有很多关于请求范围管理的问题,主要的答案是不测试范围管理,因为它是一个Spring Framework任务,它应该注意它正常工作。例如,建议就是用XML配置文件中的线程或原型类型范围替换请求范围。

对于大多数测试而言,没有关于未注册“请求”范围的投诉,并且测试运行良好。但我确实有一个案例还不够。

考虑以下案例:

@Component
@Scope("request")
public class MyService {

    @Autowired
    private MyComponent component;

    public void doSomething(String param) {
        component.doTheThing(param);
    }
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:my-scope-tweaks.xml"})
public class MyServiceTest {

    @Autowired
    private MyService service;

    @Autowired
    private MyComponent component;

    @Test
    public void test1() {
        service.doSomething("aaa");

        assertEquals("AAA", component.getTheThing());
    }

    @Test
    public void test1() {
        service.doSomething("bbb");

        assertEquals("BBB", component.getTheThing());
    }

}

我想测试MyService,它是请求范围的。 MyComponent也是请求范围。

变体A

如果我将请求范围替换为SimpleThreadScope,那么在两次测试中我都会收到MyServiceMyComponent的相同实例,因此例如test2()可以接收来自MyComponent的错误结果,因为它可以在内部包含来自之前test1()

的内部“垃圾”

变体B

如果我用原型范围替换请求范围 - 我会得到我的测试方法接收MyComponent MyService的不同实例的情况 - 所以我不能对它们执行任何断言。

所以我需要的是一种与测试方法相关的请求范围,其中所有请求范围的bean仅在test1()方法中保留然后被销毁,因此在下一个test2()内它们将是再次创造。

有可能吗?

2 个答案:

答案 0 :(得分:0)

这可能不是您想要的,但为什么您首先使用Spring来管理您的测试类?这对我来说似乎有些过分。对于单元测试,您不需要DI容器。只需模拟依赖关系并专注于您正在测试的组件或服务的封装功能。

但是,在使用现场注射时,您将无法做到这一点。您需要转换为构造函数或方法注入。

答案 1 :(得分:0)

通过使用@DirtiesContext注释方法,可以为单元测试中的每个方法接收新的上下文。这允许您在应用程序上下文中操作bean以进行一次单元测试,而不会影响其他测试。

Documentation

您的示例使用@DirtiesContext注释:

@Component
@Scope("request")
public class MyService {

    @Autowired
    private MyComponent component;

    public void doSomething(String param) {
        component.doTheThing(param);
    }
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:my-scope-tweaks.xml"})
public class MyServiceTest {

    @Autowired
    private MyService service;

    @Autowired
    private MyComponent component;

    @Test
    @DirtiesContext
    public void test1() {
        service.doSomething("aaa");

        assertEquals("AAA", component.getTheThing());
    }

    @Test
    @DirtiesContext
    public void test2() {
        service.doSomething("bbb");

        assertEquals("BBB", component.getTheThing());
    }

}

如果您班级中的所有测试方法都需要新的上下文,您也可以按如下方式对该类进行注释:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:my-scope-tweaks.xml"})
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
public class MyServiceTest {
   //Tests Here...
}