JUnit是Java中最有名的單元測試框架,用於編寫和運行可重複的測試,多數Java的開發環境都已經集成了JUnit做爲單元測試的工具。好的單元測試能極大的提升開發效率和代碼質量。java
測試類命名規則:被測試類+Test,如UserServiceTest
測試用例命名規則:test+用例方法,如testGetweb
Maven導入junit、sprint-test 、json-path相關測試包,並配置maven-suerfire-plugin插件,編輯pom.xmlspring
<dependencies> <!-- Test Unit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>4.3.10.RELEASE</version> <scope>test</scope> </dependency> <!-- Json斷言測試 --> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> <version>2.4.0</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <!-- 單元測試插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.20</version> <dependencies> <dependency> <groupId>org.apache.maven.surefire</groupId> <artifactId>surefire-junit4</artifactId> <version>2.20</version> </dependency> </dependencies> <configuration> <!-- 是否跳過測試 --> <skipTests>false</skipTests> <!-- 排除測試類 --> <excludes> <exclude>**/Base*</exclude> </excludes> </configuration> </plugin> </plugins> </build>
建立Service層測試基類,新建BaseServiceTest.java數據庫
// 配置Spring中的測試環境 @RunWith(SpringJUnit4ClassRunner.class) // 指定Spring的配置文件路徑 @ContextConfiguration(locations = {"classpath*:/spring/applicationContext.xml"}) // 測試類開啓事務,須要指定事務管理器,默認測試完成後,數據庫操做自動回滾 @Transactional(transactionManager = "transactionManager") // 指定數據庫操做不回滾,可選 @Rollback(value = false) public class BaseServiceTest { }
測試UserService類,新建測試類UserServiceTest.javaapache
public class UserServiceTest extends BaseServiceTest { private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceTest.class); @Resource private UserService userService; @Test public void testGet() { UserDO userDO = userService.get(1); Assert.assertNotNull(userDO); LOGGER.info(userDO.getUsername()); // 增長驗證斷言 Assert.assertEquals("testGet faield", "Google", userDO.getUsername()); } }
建立Controller層測試基類,新建BaseControllerTest.javajson
// 配置Spring中的測試環境 @RunWith(SpringJUnit4ClassRunner.class) // 指定測試環境使用的ApplicationContext是WebApplicationContext類型的 // value指定web應用的根 @WebAppConfiguration(value = "src/main/webapp") // 指定Spring容器層次和配置文件路徑 @ContextHierarchy({ @ContextConfiguration(name = "parent", locations = {"classpath*:/spring/applicationContext.xml"}), @ContextConfiguration(name = "child", locations = {"classpath*:/spring/applicationContext_mvc.xml"}) }) // 測試類開啓事務,須要指定事務管理器,默認測試完成後,數據庫操做自動回滾 @Transactional(transactionManager = "transactionManager") // 指定數據庫操做不回滾,可選 @Rollback(value = false) public class BaseControllerTest { }
測試IndexController類,新建測試類IndexControllerTest.javasession
public class IndexControllerTest extends BaseControllerTest { private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceTest.class); // 注入webApplicationContext @Resource private WebApplicationContext webApplicationContext; private MockMvc mockMvc; // 初始化mockMvc,在每一個測試方法前執行 @Before public void setup() { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build(); } @Test public void testIndex() throws Exception { /** * mockMvc.perform()執行一個請求 * get("/server/get")構造一個請求 * andExpect()添加驗證規則 * andDo()添加一個結果處理器 * andReturn()執行完成後返回結果 */ MvcResult result = mockMvc.perform(get("/server/get") .param("id", "1")) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.jsonPath("$.username").value("Google")) .andDo(print()) .andReturn(); LOGGER.info(result.getResponse().getContentAsString()); // 增長驗證斷言 Assert.assertNotNull(result.getResponse().getContentAsString()); } }
工程測試目錄結構以下,運行mvn test命令,自動執行maven-suerfire-plugin插件mvc
執行結果app
執行測試用例時可能拋BeanCreationNotAllowedException異常框架
[11 20:47:18,133 WARN ] [Thread-3] (AbstractApplicationContext.java:994) - Exception thrown from ApplicationListener handling ContextClosedEvent
org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'sessionFactory': Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:216)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.event.AbstractApplicationEventMulticaster.retrieveApplicationListeners(AbstractApplicationEventMulticaster.java:235)
at org.springframework.context.event.AbstractApplicationEventMulticaster.getApplicationListeners(AbstractApplicationEventMulticaster.java:192)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:128)
經過注入DefaultLifecycleProcessor解決,編輯resources/spring/applicationContext.xml
<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor"> <property name="timeoutPerShutdownPhase" value="10000"/> </bean>