Spring 2.5 ships with great support for integration testing through the classes in the org.springframework.test package. These classes allow you to dependency inject your test cases off of your existing Spring configuration, either by using your production Spring configuration file or one you've defined especially for the test case. This post explains how to annotate your JUnit 4 test cases to be autowired, but there's a lot more too the new spring-test.jar and it works with JUnit 3.8 also.
As setup for all the examples, let's assume there is a simple service that can return a String to you. Imaginative, huh?
public class MyService {
private final String name;
public MyService(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
This service is defined in a Spring XML configuration file as:
<bean id="myService" class="org.sample.MyService" >
<constructor-arg value="simple service" />
</bean>
To have Spring dependency inject our test case, we're going to have to annotate it with a little information. We'll use the standard JUnit @RunWith annotation to tell JUnit to use the Spring TestRunner, the Spring @ContextConfiguration annotation to indicate the TestCase needs injection, and the Spring @Autowired annotation to inject the MyService field by type.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public final class SimpleAutowireTest {
@Autowired
private MyService service;
@Test
public void testServiceName() {
assertEquals("simple service", service.getName());
}
}
There are a variety of ways to have Spring run your test. Besides SpringJUnit4ClassRunner.class there are also abstract TestCase objects you can inherit from, including some that will expose the ApplicationContext to you. By default, the spring configuration file for the test case will be [TestName]-context.xml. You can easily override this to point the test at your production configuration file. Also, the @Autowired annotation autowires the field by type. In the case of conflicts, you can specify the bean name using the @Qualifier annotation. Consider the following Spring configuration where there are two beans of type MyService in a file named applicationContext.xml:
<bean id="deliveryService" class="org.sample.MyService" >
<constructor-arg value="delivery service" />
</bean>
<bean id="accountingService" class="org.sample.MyService" >
<constructor-arg value="accounting service" />
</bean>
The JUnit test now requires the @Qualifier field annotation and a configuration file location as an @ContextConfiguration parameter:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"applicationContext.xml"})
public final class AdvancedAutowireTest {
@Autowired
@Qualifier("deliveryService")
private MyService service;
@Test
public void testServiceName() {
assertEquals("delivery service", service.getName());
}
}
To note: if you point the test to the production Spring configuration, then you're running integration tests and not unit tests. Integration tests are valuable and necessary, but are not always a wholesale replacement of unit tests. There's still value in isolation testing each of the components with mock dependencies. What I like about using Spring for the integration tests is that it validates the Spring mapping at test time. On my projects, we occasionally have the unit tests all passing but the Spring configuration contains a circular dependency, and we don't find out until the build hits QA. A Spring integration test pushes up error time to the test phase, when a developer can take quick action and long before QA is held up.
As is standard with JUnit, each test method runs within its own instance of the TestCase. However, the Spring TestRunner will only create one ApplicationContext for all the instances of the test method. This means that if you're test method destroys the state of a singleton bean, then downstream tests methods using that bean will fail. The way to work around this is to annotate your method with the @DirtiesContext annotation. This tells the Spring TestRunner to reload the context between test methods. For instance, these tests will pass when annotated, but fail when not:
@Autowired
private MyConfigurableService service;
@Test
@DirtiesContext
public void testServiceName1() {
assertEquals("configurable service", service.getName());
service.setName("Updating Name");
}
@Test
@DirtiesContext
public void testServiceName2() {
assertEquals("configurable service", service.getName());
service.setName("Updating Name");
}
There's a lot more in spring-test, but this is a good starting point. The transaction annotations look especially promising, including the ability to open and rollback transactions per method. The only reference I know for spring-test is the Javadoc at http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/test/package-summary.html. Those looking for a Spring starter lesson might consult the DZone RefCard.
The dependencies for spring-test are: junit, spring-context, spring-core, spring-beans, spring-tx, and commons-logging. A sample Gradle script for your build is at href="http://svn.assembla.com/svn/SampleCode/spring-test/build.gradle.
All the code for this post (including Gradle build script and IDEA project) is posted at http://svn.assembla.com/svn/SampleCode/spring-test/ and can be downloaded through subversion with the following command:
svn co http://svn.assembla.com/svn/SampleCode/spring-test
===================
这是在blogspot上找到的一个好文章,我就是根据这篇文章学会如何在单元测试中使用Spring的自动装配功能的,有时间翻译一下。
分享到:
相关推荐
它是JUnit的一个扩展,通过`@RunWith(SpringRunner.class)`注解在测试类上启用。这个注解告诉JUnit使用Spring的测试运行器来执行测试,这样我们就可以在测试中利用Spring容器的特性,如注入依赖。 接下来,让我们...
在Spring Boot项目中,我们通常使用`@RunWith(SpringRunner.class)`来运行JUnit测试,并且使用`@SpringBootTest`注解来启动一个Spring应用上下文。 Mockito是一个流行的Java模拟框架,它允许我们在测试中模拟依赖...
这里我们关注的是如何将JUnit集成到Spring Boot项目中来进行单元测试。JUnit是Java领域最常用的单元测试框架,它提供了一套简便的API来编写和运行测试用例。 首先,我们需要在Spring Boot项目中添加JUnit的依赖。在...
2. **Mockito**:一个流行的Java模拟库,可以与JUnit 5 和 Spring Boot 测试一起使用,通过 `@Autowired` 注解的模拟对象来替换真实依赖。 3. **Mockito-JUnit-Jupiter**:这是 Mockito 为JUnit 5 提供的适配器,使...
- **Spring测试框架**:包括`SpringJUnit4ClassRunner`和`SpringRunner`,它们是基于JUnit的测试运行器,能够加载Spring应用上下文。 - **测试注解**:`@SpringBootTest`用于加载整个Spring Boot应用上下文,`@...
测试类上使用`@RunWith(SpringJUnit4ClassRunner.class)`注解,将jUnit与Spring环境结合;`@SpringBootTest`注解表示当前类是SpringBoot的测试类,并加载启动类`App.class`。 ### 五、运行测试类 1. **单个方法或...
- **步骤**:通过 `@RunWith(SpringRunner.class)` 和 `@ContextConfiguration` 注解来启动 Spring 应用上下文。 **5.2 使用 @AutoBeanInject 让框架自动查找和注册需要的 bean** - **示例代码**: ```java ...
`@ExtendWith(SpringExtension.class)`可以将JUnit 5测试与Spring Boot的测试支持结合。 5. **Spring TestNG支持** 尽管JUnit 5是首选,但Spring Boot也支持TestNG。如果你更喜欢TestNG的特性,可以通过配置`...
测试类通常会使用`@RunWith(SpringRunner.class)`注解,表明它们是Spring Boot的测试,并且可能会有`@Autowired`的`DockerComposeRule`实例,用于启动和停止`docker-compose`定义的服务。 此外,`build.gradle`文件...
3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................
3. New Features and Enhancements in Spring Framework 4.0 ............................................ 17 3.1. Improved Getting Started Experience .........................................................
5. **Integration Tests**:Spring Boot支持集成测试,可以通过`@Autowired`注入实际的bean,测试整个系统的行为。 6. **TestRestTemplate**:这是一个用于测试HTTP客户端的工具,可以在集成测试中模拟HTTP请求,...