不确定为什么这个单元测试有效。 Spring ConfigurationContext 更新或创建新对象?
Not sure why this unit test works. Spring ConfigurationContext updating or creating new object?
我通过了单元测试,但我不知道它为什么会起作用。在 IntelliJ 中设置调试点表明 Autowired 属性 始终为空。我已经在 GitHub 上发布了该项目,以防有人想看一看:https://github.com/leonj1/spring_spark
下面是我在其中注释了调试点(例如#1、#2、#3)的代码。
当调试点 #1 + #2 被命中时,@Autowired PersonRoute personRoute
始终为空。这可能是因为内部静态 class 在 @ContextConfiguration
解析 @Configuration
.
之前被实例化了
但是 @ClassRule
中的 testServer
如何获得再水化的 SimpleController
?我知道 Spring 使用 Reflections 来检查和设置属性,但如果它也对已经实例化的对象执行此操作对我来说将是新闻。
我正在努力理解这一点,因为目前不知道让我对测试的信心降低。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class
})
@DatabaseSetup("persons-entities.xml")
@Transactional
public class SimpleControllerTest {
@Configuration
@ComponentScan(basePackages = {"com.jose.sandbox"})
static class SomeConfig {
// because @PropertySource doesn't work in annotation only land
@Bean
public PropertyPlaceholderConfigurer propConfig() {
// #3 debug point 3, then shows Spring creating beans
// but how does SimpleController.class get the property set?
// does this mean 2 different SimpleController objects exist in the JVM, but only one is "wired"?
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setLocation(new ClassPathResource("application.properties"));
return ppc;
}
}
@Component
public static class TestControllerTestApplication implements SparkApplication {
// #1 debug point 1 in IDE shows this as NULL
@Autowired PersonRoute personRoute;
@Override
public void init() {
new SimpleController(this.personRoute);
}
}
@ClassRule
public static SparkServer<SimpleControllerTest.TestControllerTestApplication> testServer
= new SparkServer<>(SimpleControllerTest.TestControllerTestApplication.class, 4567);
@Test
public void verifyGetAllPeople() throws Exception {
// given
String payload = null;
// when
SparkClient.UrlResponse response = testServer.getClient().doMethod("GET", "/people/count", payload);
// then
int expected = 3; // because that's how many exist in persons-entities.xml
assertEquals(200, response.status);
assertEquals(expected, Integer.parseInt(response.body));
assertNotNull(testServer.getApplication());
}
@Mock
Response response;
}
这是控制器,初始调试点为 Autowired
属性 显示 NULL。调试点再也不会被击中,那么这是如何设置的?
@Component
public class SimpleController {
// #2 debug point 2, also shows this as NULL
@Autowired PersonRoute personRoute;
public SimpleController() {}
public SimpleController(PersonRoute personRoute) {
this.personRoute = personRoute;
}
@PostConstruct
public void init() {
get("/people/count", this.personRoute);
}
}
任何帮助将不胜感激,因为在理解之前很难在此测试的基础上进行构建。
But then how does testServer
in @ClassRule
get the rehydrated SimpleController
?
没有。
其实你可以在你的测试中将下面的代码全部注释掉,测试依然通过
// @Component
public static class TestControllerTestApplication implements SparkApplication {
// #1 debug point 1 in IDE shows this as NULL
// @Autowired PersonRoute personRoute;
@Override
public void init() {
// new SimpleController(this.personRoute);
}
}
Here is the Controller which initial debug point shows NULL for the Autowired
property. The debug point never gets hit again, so how is this being set?
Spring 使用反射将 @Autowired PersonRoute
注入 SimpleController
。
基本上,发生的事情如下。
- 您指示 Spring 从
com.jose.sandbox
基础包开始执行组件扫描,这导致完全初始化 PersonRepository
、PersonRoute
和 SimpleController
beans .
PersonRoute
bean 被注入到 SimpleController
bean 中。
SimpleController
bean 的 init()
方法被 Spring 调用,因为你用 @PostConstruct
注释了它,并且通过静态 [= 向 Spark 注册了路由 get(...)
方法调用。
- 然后,Spark 测试框架在 JUnit 4 规则的 "before class" 阶段实例化您的
TestControllerTestApplication
,但该路由已经注册。因此,您的 TestControllerTestApplication
不需要实际做任何事情。这就是为什么我注释掉上面的代码。
换句话说,您只需要空的 TestControllerTestApplication
实现,因为 Spark 测试框架中的 SparkServer
需要它。没有 Spring 实现它是有意义的,但是由于您使用 Spring 配置东西的方式,没有必要 实现 它。
希望这能为您澄清一些事情。
此致,
Sam(Spring TestContext Framework 的作者)
我通过了单元测试,但我不知道它为什么会起作用。在 IntelliJ 中设置调试点表明 Autowired 属性 始终为空。我已经在 GitHub 上发布了该项目,以防有人想看一看:https://github.com/leonj1/spring_spark
下面是我在其中注释了调试点(例如#1、#2、#3)的代码。
当调试点 #1 + #2 被命中时,@Autowired PersonRoute personRoute
始终为空。这可能是因为内部静态 class 在 @ContextConfiguration
解析 @Configuration
.
但是 @ClassRule
中的 testServer
如何获得再水化的 SimpleController
?我知道 Spring 使用 Reflections 来检查和设置属性,但如果它也对已经实例化的对象执行此操作对我来说将是新闻。
我正在努力理解这一点,因为目前不知道让我对测试的信心降低。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class
})
@DatabaseSetup("persons-entities.xml")
@Transactional
public class SimpleControllerTest {
@Configuration
@ComponentScan(basePackages = {"com.jose.sandbox"})
static class SomeConfig {
// because @PropertySource doesn't work in annotation only land
@Bean
public PropertyPlaceholderConfigurer propConfig() {
// #3 debug point 3, then shows Spring creating beans
// but how does SimpleController.class get the property set?
// does this mean 2 different SimpleController objects exist in the JVM, but only one is "wired"?
PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
ppc.setLocation(new ClassPathResource("application.properties"));
return ppc;
}
}
@Component
public static class TestControllerTestApplication implements SparkApplication {
// #1 debug point 1 in IDE shows this as NULL
@Autowired PersonRoute personRoute;
@Override
public void init() {
new SimpleController(this.personRoute);
}
}
@ClassRule
public static SparkServer<SimpleControllerTest.TestControllerTestApplication> testServer
= new SparkServer<>(SimpleControllerTest.TestControllerTestApplication.class, 4567);
@Test
public void verifyGetAllPeople() throws Exception {
// given
String payload = null;
// when
SparkClient.UrlResponse response = testServer.getClient().doMethod("GET", "/people/count", payload);
// then
int expected = 3; // because that's how many exist in persons-entities.xml
assertEquals(200, response.status);
assertEquals(expected, Integer.parseInt(response.body));
assertNotNull(testServer.getApplication());
}
@Mock
Response response;
}
这是控制器,初始调试点为 Autowired
属性 显示 NULL。调试点再也不会被击中,那么这是如何设置的?
@Component
public class SimpleController {
// #2 debug point 2, also shows this as NULL
@Autowired PersonRoute personRoute;
public SimpleController() {}
public SimpleController(PersonRoute personRoute) {
this.personRoute = personRoute;
}
@PostConstruct
public void init() {
get("/people/count", this.personRoute);
}
}
任何帮助将不胜感激,因为在理解之前很难在此测试的基础上进行构建。
But then how does
testServer
in@ClassRule
get the rehydratedSimpleController
?
没有。
其实你可以在你的测试中将下面的代码全部注释掉,测试依然通过
// @Component
public static class TestControllerTestApplication implements SparkApplication {
// #1 debug point 1 in IDE shows this as NULL
// @Autowired PersonRoute personRoute;
@Override
public void init() {
// new SimpleController(this.personRoute);
}
}
Here is the Controller which initial debug point shows NULL for the
Autowired
property. The debug point never gets hit again, so how is this being set?
Spring 使用反射将 @Autowired PersonRoute
注入 SimpleController
。
基本上,发生的事情如下。
- 您指示 Spring 从
com.jose.sandbox
基础包开始执行组件扫描,这导致完全初始化PersonRepository
、PersonRoute
和SimpleController
beans . PersonRoute
bean 被注入到SimpleController
bean 中。SimpleController
bean 的init()
方法被 Spring 调用,因为你用@PostConstruct
注释了它,并且通过静态 [= 向 Spark 注册了路由get(...)
方法调用。- 然后,Spark 测试框架在 JUnit 4 规则的 "before class" 阶段实例化您的
TestControllerTestApplication
,但该路由已经注册。因此,您的TestControllerTestApplication
不需要实际做任何事情。这就是为什么我注释掉上面的代码。
换句话说,您只需要空的 TestControllerTestApplication
实现,因为 Spark 测试框架中的 SparkServer
需要它。没有 Spring 实现它是有意义的,但是由于您使用 Spring 配置东西的方式,没有必要 实现 它。
希望这能为您澄清一些事情。
此致,
Sam(Spring TestContext Framework 的作者)