ããã¯ããªã«ãããããŠæžãããã®ïŒ
Spring Bootã®ãã¹ãæ©èœã䜿ããšãMockitoãšç°¡åã«çµã¿åãããããããã«ãªããŸãã
ãã¡ãã䜿ã£ãæã®åäœããã¡ãããšèŠãŠãããããªãšæããŸããŠã
Spring BootãšMockito
Spring Bootã®Mockitoã«é¢ããããã¥ã¡ã³ãã¯ããã¡ãã
Core Features / Testing / Testing Spring Boot Applications / Mocking and Spying Beans
é¢é£ããã¯ã©ã¹ã®Javadocã¯ãã¡ãã
org.springframework.boot.test.mock.mockito (Spring Boot 3.1.5 API)
ã©ããããã®ããšãããšã@MockBean
ïŒãŸãã¯@SpyBean
ïŒã䜿ãããšã§ApplicationContext
å
ã®BeanãMockitoã®ã¢ãã¯ã«
眮ãæããããšãã§ããŸãã
Spring Boot includes a @MockBean annotation that can be used to define a Mockito mock for a bean inside your ApplicationContext. You can use the annotation to add new beans or replace a single existing bean definition.
ãããã®ã¢ãããŒã·ã§ã³ã¯ã以äžã®ç®æã§äœ¿çšã§ããŸãã
- ãã¹ãã¯ã©ã¹ãããã¹ãã¯ã©ã¹å ã®ãã£ãŒã«ã
@Configuration
ã¯ã©ã¹ããã®ãã£ãŒã«ã
äœæããã¢ãã¯ã¯ã察象ã®Beanã䜿çšããŠããã¯ã©ã¹ã«ã€ã³ãžã§ã¯ã·ã§ã³ãããŸããã€ãŸããäŸåããBeanãã¢ãã¯ã«çœ®ãæããããŸãã
When used on a field, the instance of the created mock is also injected.
ãããŠãã¢ãã¯ã¯ãã¹ãã¡ãœããã®çµäºåŸã«èªåçã«ãªã»ãããããŸãã
Mock beans are automatically reset after each test method.
䟿å©ã§ãã泚æç¹ããããããã¥ã¡ã³ãã§ã¯@MockBean
ã@SpyBean
ã®å©çšã¯ãã£ãã·ã¥ããŒã«åœ±é¿ãäžããApplicationContext
ã®
åå©çšãã§ããªããªãå¯èœæ§ã瀺åããŠããŸãã
While Springâs test framework caches application contexts between tests and reuses a context for tests sharing the same configuration, the use of @MockBean or @SpyBean influences the cache key, which will most likely increase the number of contexts.
ããã¯ãSpringã®ã³ã³ããã®äœæãå¿ èŠã«ãªãããã¹ãã®å®è¡æéã䌞ã³ãããšã«ãªããŸãã
ä»åã¯ããã®ãããã®æåãèŠãŠã¿ãããšæããŸãã
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã
$ java --version openjdk 17.0.8.1 2023-08-24 OpenJDK Runtime Environment (build 17.0.8.1+1-Ubuntu-0ubuntu122.04) OpenJDK 64-Bit Server VM (build 17.0.8.1+1-Ubuntu-0ubuntu122.04, mixed mode, sharing) $ mvn --version Apache Maven 3.9.4 (dfbb324ad4a7c8fb0bf182e6d91b0ae20e3d2dd9) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 17.0.8.1, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.15.0-87-generic", arch: "amd64", family: "unix"
ãé¡
6ã€ã®Springã®Beanãäœæãã以äžã®ãããªåãBeanã䜿ããããªå®çŸ©ãå«ãæ§æã«ããŸãã
classDiagram FooMessageService --> MessageService: ãã¹ãæã«ã¢ãã¯ã«ããŠäœ¿ã BarMessageService --> MessageService: ãã¹ãæããã®ãŸãŸäœ¿ã FooSearchService --> SearchService: ãã¹ãæã«ã¢ãã¯ã«ããŠäœ¿ã BarSearchService --> SearchService: ãã¹ãæããã®ãŸãŸäœ¿ã class FooMessageService { +getMessage() } class BarMessageService { +getMessage() } class MessageService { +get() } class FooSearchService { +find() } class BarSearchService { +find() } class SearchService { +find() }
ãã®æã泚éã®ããã«ãã¹ãæã«äŸåå
ã®Beanãã¢ãã¯ã«ããïŒããªããåãæ¿ããŠæåã確èªããããšæããŸãã
ãã¹ãã¯ãå
±æããBeanãã䜿ãåŽãã®ã¿äœæããŸãã
Spring Bootãããžã§ã¯ããäœæãã
ããã§ã¯ããŸãã¯Spring Bootãããžã§ã¯ããäœæããŸããä»åã¯äŸåé¢ä¿ã¯äžèŠãªã®ã§ã以äžã®æå®ã§äœæã
$ curl -s https://start.spring.io/starter.tgz \ -d bootVersion=3.1.5 \ -d javaVersion=17 \ -d type=maven-project \ -d name=mock-bean-example \ -d groupId=org.littlewings \ -d artifactId=mock-bean-example \ -d version=0.0.1-SNAPSHOT \ -d packageName=org.littlewings.spring.test \ -d baseDir=mock-bean-example | tar zxvf -
å±éããããã£ã¬ã¯ããªå ãžç§»åã
$ cd mock-bean-example
MavenäŸåé¢ä¿çã¯ããã®ããã«ãªã£ãŠããŸãã
<properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
çæãããã¯ã©ã¹ã¯åé€ã
$ rm src/main/java/org/littlewings/spring/test/MockBeanExampleApplication.java src/test/java/org/littlewings/spring/test/MockBeanExampleApplicationTests.java
ãœãŒã¹ã³ãŒããäœæãã
ãœãŒã¹ã³ãŒããäœæããŠãããŸãã
å ±æããBeanããã®1ã
src/main/java/org/littlewings/spring/test/service/MessageService.java
package org.littlewings.spring.test.service; import org.springframework.stereotype.Service; @Service public class MessageService { public String get() { return "Hello World!!"; } }
䜿ãåŽã®Beanã
src/main/java/org/littlewings/spring/test/service/FooMessageService.java
package org.littlewings.spring.test.service; import org.springframework.stereotype.Service; @Service public class FooMessageService { private MessageService messageService; public FooMessageService(MessageService messageService) { this.messageService = messageService; } public String getMessage() { return messageService.get(); } }
src/main/java/org/littlewings/spring/test/service/BarMessageService.java
package org.littlewings.spring.test.service; import org.springframework.stereotype.Service; @Service public class BarMessageService { private MessageService messageService; public BarMessageService(MessageService messageService) { this.messageService = messageService; } public String getMessage() { return messageService.get(); } }
å ±æããBeanããã®2ã
src/main/java/org/littlewings/spring/test/service/SearchService.java
package org.littlewings.spring.test.service; import org.springframework.stereotype.Service; import java.util.List; @Service public class SearchService { public List<String> find() { return List.of("Java", "Spring"); } }
䜿ãåŽã®Beanã
src/main/java/org/littlewings/spring/test/service/FooSearchService.java
package org.littlewings.spring.test.service; import org.springframework.stereotype.Service; import java.util.List; @Service public class FooSearchService { private SearchService searchService; public FooSearchService(SearchService searchService) { this.searchService = searchService; } public List<String> find() { return searchService.find(); } }
src/main/java/org/littlewings/spring/test/service/BarSearchService.java
package org.littlewings.spring.test.service; import org.springframework.stereotype.Service; import java.util.List; @Service public class BarSearchService { private SearchService searchService; public BarSearchService(SearchService searchService) { this.searchService = searchService; } public List<String> find() { return searchService.find(); } }
main
ã¡ãœãããæã£ãã¯ã©ã¹ãçšæããŠãããŸãã
src/main/java/org/littlewings/spring/test/App.java
package org.littlewings.spring.test; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String... args) { SpringApplication.run(App.class, args); } }
ä»åã¯ããã¹ãã®æ§æã«äœ¿ãããã ãã§ããã
ãã¹ããæžããŠç¢ºèªãã
ããã§ã¯ããã¹ããæžããŠç¢ºèªããŠãããŸãã
ä»åã¯ãã¹ãã®å®è¡é ïŒã¯ã©ã¹ãå«ãïŒãåºå®ãããã®ã§ã以äžã®èšå®ãå ¥ããŠãããŸãã
src/test/resources/junit-platform.properties
junit.jupiter.testclass.order.default=org.junit.jupiter.api.ClassOrderer$OrderAnnotation
確èªã¯ãmvn test
ã§å®æœããŠãããŸãã
ã¢ãã¯ããã¹ãããšã«ãªã»ãããããããšã確èªãã
ãŸãã¯ãããªãã¹ããçšæã
src/test/java/org/littlewings/spring/test/service/FooMessageServiceTest.java
package org.littlewings.spring.test.service; import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.boot.test.mock.mockito.MockReset; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; @SpringBootTest @TestClassOrder(ClassOrderer.OrderAnnotation.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @Order(1) class FooMessageServiceTest { @Autowired private FooMessageService fooMessageService; @MockBean private MessageService messageService; @Test @Order(1) void test1() { assertThat(mockingDetails(messageService).isMock()).isTrue(); when(messageService.get()).thenReturn("Hello Mock!!"); assertThat(fooMessageService.getMessage()).isEqualTo("Hello Mock!!"); verify(messageService, times(1)).get(); } @Test @Order(2) void test2() { assertThat(mockingDetails(messageService).isMock()).isTrue(); assertThat(fooMessageService.getMessage()).isNull(); } }
äŸåããBeanãã¢ãã¯ã«ããŸãã
@MockBean private MessageService messageService;
ãã¹ãã¯ããšãã«ã¢ãã¯ã§ããããšã確èªããŠãããæåãèŠãŠãããŸããã¢ãã¯ã®ã»ããã¢ããã¯çæ¹ã ãè¡ã£ãŠããããã¹ãã®
å®è¡é ã¯ã¢ãã¯ã®ã»ããã¢ãããè¡ãæ¹ãå
ã«ãªãããã«ããŠããŸãã
@Test @Order(1) void test1() { assertThat(mockingDetails(messageService).isMock()).isTrue(); when(messageService.get()).thenReturn("Hello Mock!!"); assertThat(fooMessageService.getMessage()).isEqualTo("Hello Mock!!"); verify(messageService, times(1)).get(); } @Test @Order(2) void test2() { assertThat(mockingDetails(messageService).isMock()).isTrue(); assertThat(fooMessageService.getMessage()).isNull(); }
ãã¹ããå®è¡ã
$ mvn test -Dtest=FooMessageServiceTest
ãã®ãã¹ãã¯ãã¹ããŸãã
ã§ã¯ããã§ã@MockBean
ã®èšå®ã以äžã®ããã«å€æŽããŸãã
@MockBean(reset = MockReset.NONE) private MessageService messageService;
ãããšããã¹ãã倱æããããã«ãªããŸãã
[ERROR] Failures: [ERROR] FooMessageServiceTest.test2:40 expected: null but was: "Hello Mock!!"
ããã¯ãããã¥ã¡ã³ãã«ãã£ã以äžã®æåãæã¡æ¶ãããã®ã§ããã€ãŸããã¢ãã¯ããªã»ãããããªããªãå¥ã®ãã¹ãã«åœ±é¿ãäžããããã«
ãªããŸããã
Mock beans are automatically reset after each test method.
ã€ãŸãããªã«ãã¢ãã¯ã®ã»ããã¢ããã®ç¶æ
ãããŠããªã以äžã®ãã¹ãããå
ã«å®è¡ãããŠã¢ãã¯ã®ã»ããã¢ãããè¡ã£ãå¥ã®ãã¹ãã®
å
容ãèŠãŠããããšã«ãªããŸãã
@Test @Order(2) void test2() { assertThat(mockingDetails(messageService).isMock()).isTrue(); assertThat(fooMessageService.getMessage()).isNull(); }
ããã©ã«ãã ãšã以äžã®æå®ãšåããšããããšã«ãªããŸããã
@MockBean(reset = MockReset.AFTER) private MessageService messageService;
ã¢ãã¯ã䜿ããªããã¹ããè¿œå ããŠãSpringã®ã³ã³ããã¹ãã®æ§ç¯ã®æ§åãèŠãŠã¿ã
次ã¯ãã¢ãã¯ã䜿ããªããã¹ããæžããŠã¿ãŸãã
src/test/java/org/littlewings/spring/test/service/BarMessageServiceTest.java
package org.littlewings.spring.test.service; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestClassOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mockingDetails; @SpringBootTest @TestClassOrder(ClassOrderer.OrderAnnotation.class) @Order(2) class BarMessageServiceTest { @Autowired private BarMessageService barMessageService; @Test void test() { Object messageService = ReflectionTestUtils.getField(barMessageService, "messageService"); assertThat(mockingDetails(messageService).isMock()).isFalse(); assertThat(barMessageService.getMessage()).isEqualTo("Hello World!!"); } }
䜿çšããŠããBeanãäŸåããŠããã®ã¯ãå ã»ã©å¥ã®ãã¹ãã§ã¢ãã¯ã«ããBeanã§ããããã¡ããã¢ãã¯ã«ãªã£ãŠããªãããšã確èªããŸãã
@Test void test() { Object messageService = ReflectionTestUtils.getField(barMessageService, "messageService"); assertThat(mockingDetails(messageService).isMock()).isFalse(); assertThat(barMessageService.getMessage()).isEqualTo("Hello World!!"); }
ãŸãã¯åäœã§å®è¡ã
$ mvn test -Dtest=BarMessageServiceTest
ãã¡ãã¯åé¡ãªããã¹ããŸãã
次ã«ãäž¡æ¹ãšãå®è¡ã
$ mvn test -Dtest=*MessageServiceTest
ãã¡ããåé¡ãªããã¹ããŸããã以äžã®ããã«Springã®ã³ã³ããã¹ãã®æ§ç¯ãããããã§è¡ãããŠããŸããŸãã
16:39:08.224 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [org.littlewings.spring.test.service.FooMessageServiceTest]: FooMessageServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 16:39:08.307 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooMessageServiceTest . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T16:39:08.667+09:00 INFO 18914 --- [ main] o.l.s.t.service.FooMessageServiceTest : Starting FooMessageServiceTest using Java 17.0.8.1 with PID 18914 (started by xxxxx in /path/to/mock-bean-example) ãçç¥ã 2023-10-22T16:39:10.338+09:00 INFO 18914 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [org.littlewings.spring.test.service.BarMessageServiceTest]: BarMessageServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2023-10-22T16:39:10.343+09:00 INFO 18914 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.BarMessageServiceTest . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T16:39:10.405+09:00 INFO 18914 --- [ main] o.l.s.t.service.BarMessageServiceTest : Starting BarMessageServiceTest using Java 17.0.8.1 with PID 18914 (started by xxxxx in /path/to/mock-bean-example) ãçç¥ã
ããã¯ãããã¥ã¡ã³ãã«æžãããŠããããã«ãã³ã³ããã¹ãã®æ§ææ å ±ãç°ãªãããåå©çšãã§ããªããªã£ãããšãæããŠããŸãã
While Springâs test framework caches application contexts between tests and reuses a context for tests sharing the same configuration, the use of @MockBean or @SpyBean influences the cache key, which will most likely increase the number of contexts.
ä»ã®ã°ã«ãŒãã³ã°ã®ãã¹ããè¿œå ããŠãã³ã³ããã¹ãã®æ§ç¯ã®æ§åãèŠãŠã¿ã
åãBeanãå ±æããæ§æãšããã³ãŒãã¯ããã1çµãããŸããããã¡ãã®ãã¹ãã³ãŒããè¿œå ããŠã¿ãŸãã
src/test/java/org/littlewings/spring/test/service/FooSearchServiceTest.java
package org.littlewings.spring.test.service; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; @SpringBootTest @Order(3) class FooSearchServiceTest { @Autowired private FooSearchService fooSearchService; @MockBean private SearchService searchService; @Order(1) void test1() { assertThat(mockingDetails(searchService).isMock()).isTrue(); when(searchService.find()).thenReturn(List.of("Mockito")); assertThat(fooSearchService.find()).isEqualTo(List.of("Mockito")); verify(searchService, times(1)).find(); } @Test @Order(2) void test2() { assertThat(mockingDetails(searchService).isMock()).isTrue(); assertThat(searchService.find()).isEmpty(); } }
src/test/java/org/littlewings/spring/test/service/BarSearchServiceTest.java
package org.littlewings.spring.test.service; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestClassOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.util.ReflectionTestUtils; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mockingDetails; @SpringBootTest @TestClassOrder(ClassOrderer.OrderAnnotation.class) @Order(4) class BarSearchServiceTest { @Autowired private BarSearchService barSearchService; @Test void test1() { Object searchService = ReflectionTestUtils.getField(barSearchService, "searchService"); assertThat(mockingDetails(searchService).isMock()).isFalse(); assertThat(barSearchService.find()).isEqualTo(List.of("Java", "Spring")); } }
ãã¹ããšããŠå®è£ ããŠããå 容ããç°ãªããŸããã確èªããŠãããã€ã³ãã¯å ã»ã©ã®ãã®ãšåãã§ãã
ãšããããã§ããã¹ããå®è¡ããŠã¿ãŸãã
$ mvn test
ãã¹ãã¯åé¡ãªããã¹ããŸãããSpringã®ã³ã³ããã¹ãã®æ§ç¯ã¯3åè¡ãããŸããã
16:45:35.204 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [org.littlewings.spring.test.service.FooMessageServiceTest]: FooMessageServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 16:45:35.290 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooMessageServiceTest . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T16:45:35.623+09:00 INFO 19254 --- [ main] o.l.s.t.service.FooMessageServiceTest : Starting FooMessageServiceTest using Java 17.0.8.1 with PID 19254 (started by xxxxx in /path/to/mock-bean-example) ãçç¥ã 2023-10-22T16:45:37.138+09:00 INFO 19254 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [org.littlewings.spring.test.service.BarMessageServiceTest]: BarMessageServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2023-10-22T16:45:37.142+09:00 INFO 19254 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.BarMessageServiceTest . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T16:45:37.203+09:00 INFO 19254 --- [ main] o.l.s.t.service.BarMessageServiceTest : Starting BarMessageServiceTest using Java 17.0.8.1 with PID 19254 (started by xxxxx in /path/to/mock-bean-example) ãçç¥ã 2023-10-22T16:45:37.345+09:00 INFO 19254 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [org.littlewings.spring.test.service.FooSearchServiceTest]: FooSearchServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2023-10-22T16:45:37.349+09:00 INFO 19254 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooSearchServiceTest . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T16:45:37.388+09:00 INFO 19254 --- [ main] o.l.s.test.service.FooSearchServiceTest : Starting FooSearchServiceTest using Java 17.0.8.1 with PID 19254 (started by xxxxx in /path/to/mock-bean-example) ãçç¥ã 2023-10-22T16:45:37.556+09:00 INFO 19254 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [org.littlewings.spring.test.service.BarSearchServiceTest]: BarSearchServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2023-10-22T16:45:37.558+09:00 INFO 19254 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.BarSearchServiceTest
4åã§ã¯ãªãã®ã¯ãã¢ãã¯ã䜿ã£ãŠããªãBarMessageServiceTest
ãšBarSearchServiceTest
ã§ã¯ãã£ãã·ã¥ããã³ã³ããã¹ãã䜿ãåãã
ããã§ããã
ãã°ãããèŠããšãããããå 容ã¯ãã€ãåºãŠããŸãã
16:45:35.204 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [org.littlewings.spring.test.service.FooMessageServiceTest]: FooMessageServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 16:45:35.290 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooMessageServiceTest
ã³ã³ããã¹ããäœãçŽãããšã«ãªã£ãæã¯ã以äžã®ãã°ãåºåããããã§ããã
2023-10-22T16:45:37.203+09:00 INFO 19254 --- [ main] o.l.s.t.service.BarMessageServiceTest : Starting BarMessageServiceTest using Java 17.0.8.1 with PID 19254 (started by xxxxx in /path/to/mock-bean-example)
åŸç¶ã§èµ·åããBarSearchServiceTest
ã«ã¯ããã®ãã°ããããŸããã§ããã
ã§ã¯ãã¢ãã¯ã䜿ã£ããã¹ãã®ã¿ã§ã¯ã©ãã§ããããã
$ mvn test -Dtest=Foo*ServiceTest
ãã¡ããããŒãç°ãªãã®ã§ã2åã³ã³ããã¹ããæ§ç¯ãããŸãã
16:49:29.975 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [org.littlewings.spring.test.service.FooMessageServiceTest]: FooMessageServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 16:49:30.064 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooMessageServiceTest . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T16:49:30.369+09:00 INFO 19387 --- [ main] o.l.s.t.service.FooMessageServiceTest : Starting FooMessageServiceTest using Java 17.0.8.1 with PID 19387 (started by xxxxx in /path/to/mock-bean-example) ãçç¥ã 2023-10-22T16:49:31.727+09:00 INFO 19387 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [org.littlewings.spring.test.service.FooSearchServiceTest]: FooSearchServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2023-10-22T16:49:31.731+09:00 INFO 19387 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooSearchServiceTest . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T16:49:31.783+09:00 INFO 19387 --- [ main] o.l.s.test.service.FooSearchServiceTest : Starting FooSearchServiceTest using Java 17.0.8.1 with PID 19387 (started by xxxxx in /path/to/mock-bean-example)
ãã¹ã察象ã¯åãã§ãã¢ãã¯ã䜿ããªããã¹ããè¿œå ãã
ãããŸã§ã§ããªããšãªãæåã¯ç¢ºèªã§ããæ°ãããŸãã
ããã§ã¯ããã¹ã察象ã¯åãã§ãã¢ãã¯ã¯äœ¿ããªããã¿ãŒã³ãã®ãã¹ããè¿œå ããŠã¿ãŸããããçµæã¯ãããæ°ã¯ããŸããã
ãããããã®ã§ããã
src/test/java/org/littlewings/spring/test/service/FooMessageService2Test.java
package org.littlewings.spring.test.service; import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestClassOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mockingDetails; @SpringBootTest @TestClassOrder(ClassOrderer.OrderAnnotation.class) @Order(5) public class FooMessageService2Test { @Autowired private FooMessageService fooMessageService; @Test void test1() { Object messageService = ReflectionTestUtils.getField(fooMessageService, "messageService"); assertThat(mockingDetails(messageService).isMock()).isFalse(); assertThat(fooMessageService.getMessage()).isEqualTo("Hello World!!"); } }
å®è¡ã
$ mvn test -Dtest=FooMessageService*Test
äºæ³ã§ããæåã§ãããã³ã³ããã¹ãã2åæ§ç¯ãããŸãã
16:55:55.763 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [org.littlewings.spring.test.service.FooMessageServiceTest]: FooMessageServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 16:55:55.862 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooMessageServiceTest . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T16:55:56.185+09:00 INFO 19782 --- [ main] o.l.s.t.service.FooMessageServiceTest : Starting FooMessageServiceTest using Java 17.0.8.1 with PID 19782 (started by xxxxx in /path/to/mock-bean-example) ãçç¥ã 2023-10-22T16:55:57.792+09:00 INFO 19782 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [org.littlewings.spring.test.service.FooMessageService2Test]: FooMessageService2Test does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2023-10-22T16:55:57.798+09:00 INFO 19782 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooMessageService2Test . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T16:55:57.843+09:00 INFO 19782 --- [ main] o.l.s.t.service.FooMessageService2Test : Starting FooMessageService2Test using Java 17.0.8.1 with PID 19782 (started by xxxxx in /path/to/mock-bean-example)
å šéšã®ãã¹ããå®è¡ããå Žåã¯ãã¢ãã¯ã䜿ããªããã¹ãã¯ããããã§ã³ã³ããã¹ããå ±æã§ããã®ã§ãã³ã³ããã¹ã®æ§ç¯ã¯3åã«ãªããŸãã
$ mvn test
ã¢ãã¯å¯Ÿè±¡ãåããã¹ããè¿œå ãã
æåŸã«ãã®ç¶æ
ã§ãã¢ãã¯å¯Ÿè±¡ãåããã¹ããããã²ãšã€è¿œå ããŸããFooMessageServiceTest
ã®ã³ããŒã§ããã
src/test/java/org/littlewings/spring/test/service/FooMessageService3Test.java
package org.littlewings.spring.test.service; import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.*; @SpringBootTest @TestClassOrder(ClassOrderer.OrderAnnotation.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @Order(6) class FooMessageService3Test { @Autowired private FooMessageService fooMessageService; @MockBean private MessageService messageService; @Test @Order(1) void test1() { assertThat(mockingDetails(messageService).isMock()).isTrue(); when(messageService.get()).thenReturn("Hello Mock!!"); assertThat(fooMessageService.getMessage()).isEqualTo("Hello Mock!!"); verify(messageService, times(1)).get(); } @Test @Order(2) void test2() { assertThat(mockingDetails(messageService).isMock()).isTrue(); assertThat(fooMessageService.getMessage()).isNull(); } }
ããã¯ã©ããªãããšãããš
$ mvn test -Dtest=FooMessageService*Test
å
ã»ã©ã¢ãã¯ã䜿ããªããã¹ããè¿œå ããã®ã§ãã³ã³ããã¹ãã®æ§ç¯åæ°ã¯2åã«ãªã£ãŠããŸãããã¢ãã¯ãå«ããŠå®çŸ©ãåãã§ããã°
ã³ã³ããã¹ãã䜿ãåãããïŒFooMessageServiceTest
ãšFooMessageService3Test
ã§å®çŸ©ãåããªã®ã§ãåãã³ã³ããã¹ããåå©çšãããïŒ
ããšã確èªã§ããŸãã
ing.test.service.FooMessageServiceTest]: FooMessageServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 17:08:26.641 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooMessageServiceTest . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T17:08:27.049+09:00 INFO 20970 --- [ main] o.l.s.t.service.FooMessageServiceTest : Starting FooMessageServiceTest using Java 17.0.8.1 with PID 20970 (started by xxxxx in /path/to/mock-bean-example) ãçç¥ã 2023-10-22T17:08:29.538+09:00 INFO 20970 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [org.littlewings.spring.test.service.FooMessageService2Test]: FooMessageService2Test does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2023-10-22T17:08:29.546+09:00 INFO 20970 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooMessageService2Test . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.1.5) 2023-10-22T17:08:29.644+09:00 INFO 20970 --- [ main] o.l.s.t.service.FooMessageService2Test : Starting FooMessageService2Test using Java 17.0.8.1 with PID 20970 (started by xxxxx in /path/to/mock-bean-example) ãçç¥ã 2023-10-22T17:08:29.948+09:00 INFO 20970 --- [ main] t.c.s.AnnotationConfigContextLoaderUtils : Could not detect default configuration classes for test class [org.littlewings.spring.test.service.FooMessageService3Test]: FooMessageService3Test does not declare any static, non-private, non-final, nested classes annotated with @Configuration. 2023-10-22T17:08:29.956+09:00 INFO 20970 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Found @SpringBootConfiguration org.littlewings.spring.test.App for test class org.littlewings.spring.test.service.FooMessageService3Test
ãããªãšããã§ããããã
ãããã«
Spring TestãšMockitoïŒ@MockBean
ïŒãçµã¿åãããæã«ãã©ã®ãããªåäœã«ãªãã®ã確èªããŠã¿ãŸããã
â»@SpyBean
ã¯ãã¹ããŠããŸãã
@MockBean
ã¯Spring Bootã§Mockitoã䜿ãæã«ã¯äŸ¿å©ã§ãããããããæåã«ãªããšããã®ãæŒãããŠãããªããšãããªãæ°ãããŸããã
ãã¹ãã®é床ãåé¡ã«ãªã£ãŠãããããªæã¯ã@MockBean
ã«é Œããã«èªåã§ã¢ãã¯ãšããŠäœæããBeanãå·®ãæ¿ããŠããã¹ãã®çµäºæã«
æ»ããããªããšãããã®ãè¯ããããªæ°ãããŸãã