在单元测试中有很多关于请求范围管理的问题,主要的答案是不测试范围管理,因为它是一个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
也是请求范围。
如果我将请求范围替换为SimpleThreadScope
,那么在两次测试中我都会收到MyService
和MyComponent
的相同实例,因此例如test2()
可以接收来自MyComponent
的错误结果,因为它可以在内部包含来自之前test1()
如果我用原型范围替换请求范围 - 我会得到我的测试方法接收MyComponent
MyService
的不同实例的情况 - 所以我不能对它们执行任何断言。
所以我需要的是一种与测试方法相关的请求范围,其中所有请求范围的bean仅在test1()
方法中保留然后被销毁,因此在下一个test2()
内它们将是再次创造。
有可能吗?
答案 0 :(得分:0)
这可能不是您想要的,但为什么您首先使用Spring来管理您的测试类?这对我来说似乎有些过分。对于单元测试,您不需要DI容器。只需模拟依赖关系并专注于您正在测试的组件或服务的封装功能。
但是,在使用现场注射时,您将无法做到这一点。您需要转换为构造函数或方法注入。
答案 1 :(得分:0)
通过使用@DirtiesContext
注释方法,可以为单元测试中的每个方法接收新的上下文。这允许您在应用程序上下文中操作bean以进行一次单元测试,而不会影响其他测试。
您的示例使用@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...
}