Like Share Discussion Bookmark Smile

J.J. Huang   2019-03-13   Spring Boot   瀏覽次數:

SpringBoot - 第二章 | 測試案例

Spring Boot Test (Junit)

一個好的工程師,基本上在寫完每個功能,都要針對其功能撰寫一個測試程式,好處是提升程式品質以及共同開發時確保自身之功能邏輯是正確的。而且最近幾年DevOps的盛行,創造了一個新的軟體工程的開發,最終目的達到持續整合,持續改善,持續交付。

加入pom的依賴

1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

編寫測試案例

  • 新建test controller package
1
com.jj.learning.springboot.chapter2.controller
  • 新建DemoControllerTest.class

註:個人建議,每個測試都應該和對應的被測試類包路徑一致。同時測試類的名稱是被測試的類名+Test

執行測試案例

  • 對著DemoControllerTest -> 右键 -> Run As –> JUnit Test
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
console:

16:49:53.901 [main] DEBUG org.springframework.test.context.junit4.SpringJUnit4ClassRunner - SpringJUnit4ClassRunner constructor called with [class com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:53.910 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate]
16:49:53.925 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support.DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)]
16:49:53.951 [main] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper]
16:49:53.968 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest], using SpringBootContextLoader
16:49:53.972 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]: class path resource [com/jj/learning/springboot/chapter2/controller/DemoControllerTest-context.xml] does not exist
16:49:53.973 [main] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]: class path resource [com/jj/learning/springboot/chapter2/controller/DemoControllerTestContext.groovy] does not exist
16:49:53.973 [main] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]: no resource found for suffixes {-context.xml, Context.groovy}.
16:49:53.974 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]: DemoControllerTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
16:49:54.027 [main] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.134 [main] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [/Users/morose/Documents/workspace-SpringBoot/chapter-2/target/classes/com/jj/learning/springboot/chapter2/Chapter2Application.class]
16:49:54.136 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration com.jj.learning.springboot.chapter2.Chapter2Application for test class com.jj.learning.springboot.chapter2.controller.DemoControllerTest
16:49:54.247 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - @TestExecutionListeners is not present for class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]: using defaults.
16:49:54.247 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
16:49:54.259 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Skipping candidate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener] due to a missing dependency. Specify custom listener classes or make the default listener classes and their required dependencies available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource]
16:49:54.259 [main] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Skipping candidate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener] due to a missing dependency. Specify custom listener classes or make the default listener classes and their required dependencies available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute]
16:49:54.260 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@6ef888f6, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@10e92f8f, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@7ce3cb8e, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@78b66d36, org.springframework.test.context.support.DirtiesContextTestExecutionListener@5223e5ee, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@bef2d72, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@69b2283a, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@22a637e7, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@6fe7aac8, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@1d119efb]
16:49:54.261 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.261 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.274 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.274 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.275 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.275 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.275 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.275 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.280 [main] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext@48ae9b55 testClass = DemoControllerTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@1700915 testClass = DemoControllerTest, locations = '{}', classes = '{class com.jj.learning.springboot.chapter2.Chapter2Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=0}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@527740a2, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@370736d9, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@7b49cea0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@49fc609f], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> false]], class annotated with @DirtiesContext [false] with mode [null].
16:49:54.280 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved @ProfileValueSourceConfiguration [null] for test class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.280 [main] DEBUG org.springframework.test.annotation.ProfileValueUtils - Retrieved ProfileValueSource type [class org.springframework.test.annotation.SystemProfileValueSource] for class [com.jj.learning.springboot.chapter2.controller.DemoControllerTest]
16:49:54.284 [main] DEBUG org.springframework.test.context.support.DependencyInjectionTestExecutionListener - Performing dependency injection for test context [[DefaultTestContext@48ae9b55 testClass = DemoControllerTest, testInstance = com.jj.learning.springboot.chapter2.controller.DemoControllerTest@4f209819, testMethod = [null], testException = [null], mergedContextConfiguration = [WebMergedContextConfiguration@1700915 testClass = DemoControllerTest, locations = '{}', classes = '{class com.jj.learning.springboot.chapter2.Chapter2Application}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=0}', contextCustomizers = set[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@527740a2, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@370736d9, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@7b49cea0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@49fc609f], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map['org.springframework.test.context.web.ServletTestExecutionListener.activateListener' -> false]]].
16:49:54.303 [main] DEBUG org.springframework.test.context.support.TestPropertySourceUtils - Adding inlined properties to environment: {spring.jmx.enabled=false, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=0}

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.3.RELEASE)

2019-03-13 16:49:54.569 INFO 9954 --- [ main] c.j.l.s.c.controller.DemoControllerTest : Starting DemoControllerTest on localhost with PID 9954 (started by morose in /Users/morose/Documents/workspace-SpringBoot/chapter-2)
2019-03-13 16:49:54.571 INFO 9954 --- [ main] c.j.l.s.c.controller.DemoControllerTest : No active profile set, falling back to default profiles: default
2019-03-13 16:49:55.768 INFO 9954 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 0 (http)
2019-03-13 16:49:55.806 INFO 9954 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-03-13 16:49:55.806 INFO 9954 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.16]
2019-03-13 16:49:55.819 INFO 9954 --- [ main] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/morose/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
2019-03-13 16:49:55.939 INFO 9954 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-03-13 16:49:55.939 INFO 9954 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1349 ms
2019-03-13 16:49:56.332 INFO 9954 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-03-13 16:49:56.662 INFO 9954 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 55353 (http) with context path ''
2019-03-13 16:49:56.666 INFO 9954 --- [ main] c.j.l.s.c.controller.DemoControllerTest : Started DemoControllerTest in 2.359 seconds (JVM running for 3.203)
2019-03-13 16:49:56.819 INFO 9954 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring TestDispatcherServlet ''
2019-03-13 16:49:56.819 INFO 9954 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Initializing Servlet ''
2019-03-13 16:49:56.832 INFO 9954 --- [ main] o.s.t.web.servlet.TestDispatcherServlet : Completed initialization in 13 ms
2019-03-13 16:49:56.919 INFO 9954 --- [ Thread-3] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
  • 成功的案例圖
1
綠色就表示沒問題啦,沒有Failures。

  • 失敗的案例圖
1
2
此案例是預期httpStatus 為404,但是回傳為非預期的 200
java.lang.AssertionError: Status expected:<404> but was:<200>

註:這邊只做基本的簡單使用範例教學,像MockMvc的詳細用法並沒有深入,大家可自行搜索下,畢竟我也用的不多。