├── .gitignore ├── CHEATSHEET.md ├── non-reactive ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── car │ │ │ ├── CarsApplication.java │ │ │ ├── domain │ │ │ ├── Car.java │ │ │ └── CarRepository.java │ │ │ ├── service │ │ │ └── CarService.java │ │ │ └── web │ │ │ ├── CarNotFoundException.java │ │ │ └── CarsController.java │ └── resources │ │ └── application.properties │ └── test │ └── java │ └── com │ └── example │ └── car │ ├── CachingTest.java │ ├── IntegrationTests.java │ ├── domain │ └── CarRepositoryTests.java │ ├── service │ └── CarServiceTest.java │ └── web │ └── CarsControllerTests.java └── reactive ├── main ├── java │ └── com │ │ └── example │ │ └── car │ │ ├── CarsApplication.java │ │ ├── domain │ │ ├── Car.java │ │ └── CarRepository.java │ │ └── web │ │ └── CarController.java └── resources │ └── application.properties ├── pom.xml └── test └── java └── com └── example └── car ├── IntegrationTests.java ├── domain └── CarRepositoryTests.java └── web └── CarControllerTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ -------------------------------------------------------------------------------- /CHEATSHEET.md: -------------------------------------------------------------------------------- 1 | ## Annotations 2 | 3 | | Annotation | Description 4 | |------------------------------- |-------------- 5 | |@RunWith(SpringRunner.class) | @SpringJUnit4ClassRunner alias; add for junit test support 6 | | | 7 | |@SpringBootTest | Bootstrap test with SpringBoot support, load application.properties; 8 | | | specify random or specific port to start app; TestRestTemplate bean made available; 9 | | | 10 | |@WebMvcTest | Use in combination with SpringRunner to load context relevant spring mvc components 11 | | | 12 | |@RunWith(MockitoJUnitRunner.class) | Initializes mocks so no need to initMocks(this); automatic validation of framework usage 13 | | | 14 | |@DataJpaTest | Loads jpa relevant config; uses in-memory db by default, override with @AutoConfigureTestDatabase 15 | | | 16 | |@AutoConfigureTestDatabase | If you do not want to use auto-configured test database, use this to configure a test db 17 | | | 18 | |@MockBean | Use with SpringRunner class to mock components in test 19 | | | 20 | |@Mock | Similar to @MockBean but without spring support; use with MockitoJUnitRunner 21 | | | 22 | |@AutoConfigureMockMvc | More control of mock-mvc, disable spring security bits etc 23 | | | 24 | |@WebFluxTest | Use in combination with SpringRunner to load context relevant spring WebFlux components 25 | | | 26 | |@DataMongoTest | Use in combination with SpringRunner for testing MongoDB components; uses in-memory MongoDB by default 27 | -------------------------------------------------------------------------------- /non-reactive/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | mbhave-tdd-demo 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | non-reactive-tdd-demo 12 | Demo project for TDD with Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.0.BUILD-SNAPSHOT 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-data-jpa 35 | 36 | 37 | mysql 38 | mysql-connector-java 39 | 40 | 41 | com.h2database 42 | h2 43 | test 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-starter-test 48 | test 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-maven-plugin 57 | 58 | 59 | 60 | 61 | 62 | 63 | spring-snapshots 64 | Spring Snapshots 65 | https://repo.spring.io/snapshot 66 | 67 | true 68 | 69 | 70 | 71 | spring-milestones 72 | Spring Milestones 73 | https://repo.spring.io/milestone 74 | 75 | false 76 | 77 | 78 | 79 | 80 | 81 | 82 | spring-snapshots 83 | Spring Snapshots 84 | https://repo.spring.io/snapshot 85 | 86 | true 87 | 88 | 89 | 90 | spring-milestones 91 | Spring Milestones 92 | https://repo.spring.io/milestone 93 | 94 | false 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /non-reactive/src/main/java/com/example/car/CarsApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.car; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cache.annotation.EnableCaching; 6 | 7 | @SpringBootApplication 8 | @EnableCaching 9 | public class CarsApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(CarsApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /non-reactive/src/main/java/com/example/car/domain/Car.java: -------------------------------------------------------------------------------- 1 | package com.example.car.domain; 2 | 3 | import javax.persistence.Entity; 4 | import javax.persistence.GeneratedValue; 5 | import javax.persistence.Id; 6 | 7 | @Entity 8 | public class Car { 9 | 10 | @Id 11 | @GeneratedValue 12 | private Long id; 13 | 14 | private String name; 15 | 16 | private String type; 17 | 18 | public Car(String name, String type) { 19 | this.name = name; 20 | this.type = type; 21 | } 22 | 23 | public String getName() { 24 | return this.name; 25 | } 26 | 27 | public void setName(String name) { 28 | this.name = name; 29 | } 30 | 31 | public String getType() { 32 | return this.type; 33 | } 34 | 35 | public void setType(String type) { 36 | this.type = type; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /non-reactive/src/main/java/com/example/car/domain/CarRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.car.domain; 2 | 3 | import org.springframework.data.repository.CrudRepository; 4 | 5 | public interface CarRepository extends CrudRepository { 6 | 7 | Car findByName(String name); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /non-reactive/src/main/java/com/example/car/service/CarService.java: -------------------------------------------------------------------------------- 1 | package com.example.car.service; 2 | 3 | import com.example.car.domain.Car; 4 | import com.example.car.domain.CarRepository; 5 | import com.example.car.web.CarNotFoundException; 6 | 7 | import org.springframework.cache.annotation.Cacheable; 8 | import org.springframework.stereotype.Service; 9 | 10 | @Service 11 | public class CarService { 12 | 13 | private CarRepository carRepository; 14 | 15 | public CarService(CarRepository carRepository) { 16 | this.carRepository = carRepository; 17 | } 18 | 19 | @Cacheable("cars") 20 | public Car getCarDetails(String name) { 21 | Car car = carRepository.findByName(name); 22 | if(car == null) { 23 | throw new CarNotFoundException(); 24 | } 25 | return car; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /non-reactive/src/main/java/com/example/car/web/CarNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.example.car.web; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.NOT_FOUND) 7 | public class CarNotFoundException extends RuntimeException { 8 | } 9 | -------------------------------------------------------------------------------- /non-reactive/src/main/java/com/example/car/web/CarsController.java: -------------------------------------------------------------------------------- 1 | package com.example.car.web; 2 | 3 | import com.example.car.domain.Car; 4 | import com.example.car.service.CarService; 5 | 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.PathVariable; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | @RestController 11 | public class CarsController { 12 | 13 | private final CarService carService; 14 | 15 | public CarsController(CarService carService) { 16 | this.carService = carService; 17 | } 18 | 19 | @GetMapping("/cars/{name}") 20 | public Car getCar(@PathVariable String name) { 21 | Car car = this.carService.getCarDetails(name); 22 | if (car == null) { 23 | throw new CarNotFoundException(); 24 | } 25 | return car; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /non-reactive/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.datasource.url=jdbc:mysql://localhost:3306/test?user=root -------------------------------------------------------------------------------- /non-reactive/src/test/java/com/example/car/CachingTest.java: -------------------------------------------------------------------------------- 1 | package com.example.car; 2 | 3 | import com.example.car.domain.Car; 4 | import com.example.car.domain.CarRepository; 5 | import com.example.car.service.CarService; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | import org.springframework.boot.test.mock.mockito.MockBean; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | 15 | import static org.mockito.ArgumentMatchers.anyString; 16 | import static org.mockito.BDDMockito.given; 17 | import static org.mockito.Mockito.times; 18 | import static org.mockito.Mockito.verify; 19 | 20 | @RunWith(SpringRunner.class) 21 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE) 22 | @AutoConfigureTestDatabase 23 | public class CachingTest { 24 | 25 | @Autowired 26 | private CarService service; 27 | 28 | @MockBean 29 | private CarRepository repository; 30 | 31 | @Test 32 | public void getCar_ReturnsCachedValue() throws Exception { 33 | given(repository.findByName(anyString())).willReturn(new Car("prius", "hybrid")); 34 | service.getCarDetails("prius"); 35 | service.getCarDetails("prius"); 36 | verify(repository, times(1)).findByName("prius"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /non-reactive/src/test/java/com/example/car/IntegrationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.car; 2 | 3 | import com.example.car.domain.Car; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.boot.test.web.client.TestRestTemplate; 10 | import org.springframework.http.HttpStatus; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | 14 | import static org.assertj.core.api.Assertions.assertThat; 15 | 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 18 | public class IntegrationTests { 19 | 20 | @Autowired 21 | private TestRestTemplate testRestTemplate; 22 | 23 | @Test 24 | public void getCar_WithName_ReturnsCar() { 25 | ResponseEntity responseEntity = this.testRestTemplate.getForEntity("/cars/{name}", Car.class, "prius"); 26 | Car car = responseEntity.getBody(); 27 | assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); 28 | assertThat(car.getName()).isEqualTo("prius"); 29 | assertThat(car.getType()).isEqualTo("hybrid"); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /non-reactive/src/test/java/com/example/car/domain/CarRepositoryTests.java: -------------------------------------------------------------------------------- 1 | package com.example.car.domain; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; 8 | import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | @RunWith(SpringRunner.class) 14 | @DataJpaTest 15 | public class CarRepositoryTests { 16 | 17 | @Autowired 18 | private CarRepository repository; 19 | 20 | @Autowired 21 | private TestEntityManager testEntityManager; 22 | 23 | @Test 24 | public void findByName_ReturnsCar() throws Exception { 25 | Car savedCar = testEntityManager.persistFlushFind(new Car("prius", "hybrid")); 26 | Car car = this.repository.findByName("prius"); 27 | assertThat(car.getName()).isEqualTo(savedCar.getName()); 28 | assertThat(car.getType()).isEqualTo(savedCar.getType()); 29 | } 30 | } -------------------------------------------------------------------------------- /non-reactive/src/test/java/com/example/car/service/CarServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.example.car.service; 2 | 3 | import com.example.car.domain.Car; 4 | import com.example.car.domain.CarRepository; 5 | import com.example.car.web.CarNotFoundException; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.mockito.Mock; 10 | import org.mockito.junit.MockitoJUnitRunner; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | import static org.mockito.BDDMockito.given; 14 | 15 | @RunWith(MockitoJUnitRunner.class) 16 | public class CarServiceTest { 17 | 18 | @Mock 19 | private CarRepository carRepository; 20 | 21 | private CarService carService; 22 | 23 | @Before 24 | public void setUp() throws Exception { 25 | carService = new CarService(carRepository); 26 | } 27 | 28 | @Test 29 | public void getCarDetails_returnsCarInfo() { 30 | given(carRepository.findByName("prius")).willReturn(new Car("prius", "hybrid")); 31 | 32 | Car car = carService.getCarDetails("prius"); 33 | 34 | assertThat(car.getName()).isEqualTo("prius"); 35 | assertThat(car.getType()).isEqualTo("hybrid"); 36 | } 37 | 38 | @Test(expected = CarNotFoundException.class) 39 | public void getCarDetails_whenCarNotFound() throws Exception { 40 | given(carRepository.findByName("prius")).willReturn(null); 41 | 42 | carService.getCarDetails("prius"); 43 | } 44 | } -------------------------------------------------------------------------------- /non-reactive/src/test/java/com/example/car/web/CarsControllerTests.java: -------------------------------------------------------------------------------- 1 | package com.example.car.web; 2 | 3 | import com.example.car.domain.Car; 4 | import com.example.car.service.CarService; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 10 | import org.springframework.boot.test.mock.mockito.MockBean; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | import org.springframework.test.web.servlet.MockMvc; 13 | 14 | import static org.mockito.ArgumentMatchers.any; 15 | import static org.mockito.Mockito.when; 16 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 17 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 18 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 19 | 20 | @RunWith(SpringRunner.class) 21 | @WebMvcTest 22 | public class CarsControllerTests { 23 | 24 | @Autowired 25 | private MockMvc mockMvc; 26 | 27 | @MockBean 28 | private CarService carService; 29 | 30 | @Test 31 | public void getCar_WithName_ReturnsCar() throws Exception { 32 | when(this.carService.getCarDetails("prius")).thenReturn(new Car("prius", "hybrid")); 33 | this.mockMvc.perform(get("/cars/{name}", "prius")) 34 | .andExpect(status().isOk()) 35 | .andExpect(jsonPath("name").value("prius")) 36 | .andExpect(jsonPath("type").value("hybrid")); 37 | } 38 | 39 | @Test 40 | public void getCar_NotFound_Returns404() throws Exception { 41 | when(this.carService.getCarDetails(any())).thenReturn(null); 42 | this.mockMvc.perform(get("/cars/{name}", "prius")) 43 | .andExpect(status().isNotFound()); 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /reactive/main/java/com/example/car/CarsApplication.java: -------------------------------------------------------------------------------- 1 | package com.example.car; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class CarsApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(CarsApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /reactive/main/java/com/example/car/domain/Car.java: -------------------------------------------------------------------------------- 1 | package com.example.car.domain; 2 | 3 | import org.springframework.data.annotation.Id; 4 | import org.springframework.data.mongodb.core.mapping.Document; 5 | 6 | @Document 7 | public class Car { 8 | 9 | @Id 10 | private String id; 11 | 12 | private String name; 13 | 14 | private String type; 15 | 16 | public Car() { 17 | } 18 | 19 | public Car(String name, String type) { 20 | this.name = name; 21 | this.type = type; 22 | } 23 | 24 | public String getName() { 25 | return this.name; 26 | } 27 | 28 | public void setName(String name) { 29 | this.name = name; 30 | } 31 | 32 | public String getType() { 33 | return this.type; 34 | } 35 | 36 | public void setType(String type) { 37 | this.type = type; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /reactive/main/java/com/example/car/domain/CarRepository.java: -------------------------------------------------------------------------------- 1 | package com.example.car.domain; 2 | 3 | import reactor.core.publisher.Mono; 4 | 5 | import org.springframework.data.repository.reactive.ReactiveCrudRepository; 6 | 7 | public interface CarRepository extends ReactiveCrudRepository { 8 | 9 | Mono findByName(String name); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /reactive/main/java/com/example/car/web/CarController.java: -------------------------------------------------------------------------------- 1 | package com.example.car.web; 2 | 3 | import com.example.car.domain.Car; 4 | import com.example.car.domain.CarRepository; 5 | import reactor.core.publisher.Mono; 6 | 7 | import org.springframework.web.bind.annotation.GetMapping; 8 | import org.springframework.web.bind.annotation.PathVariable; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | @RestController 12 | public class CarController { 13 | 14 | private final CarRepository carRepository; 15 | 16 | public CarController(CarRepository carRepository) { 17 | this.carRepository = carRepository; 18 | } 19 | 20 | @GetMapping("/cars/{name}") 21 | public Mono getCar (@PathVariable String name) { 22 | return this.carRepository.findByName(name); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /reactive/main/resources/application.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbhave/tdd-with-spring-boot/dabcbd2d5eb547a36c84011663cfd6c48b089602/reactive/main/resources/application.properties -------------------------------------------------------------------------------- /reactive/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | reactive-tdd-demo 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | reactive-tdd-demo 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.0.BUILD-SNAPSHOT 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-data-mongodb-reactive 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-webflux 35 | 36 | 37 | de.flapdoodle.embed 38 | de.flapdoodle.embed.mongo 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-starter-test 43 | test 44 | 45 | 46 | io.projectreactor 47 | reactor-test 48 | test 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-maven-plugin 57 | 58 | 59 | 60 | 61 | 62 | 63 | spring-snapshots 64 | Spring Snapshots 65 | https://repo.spring.io/snapshot 66 | 67 | true 68 | 69 | 70 | 71 | spring-milestones 72 | Spring Milestones 73 | https://repo.spring.io/milestone 74 | 75 | false 76 | 77 | 78 | 79 | 80 | 81 | 82 | spring-snapshots 83 | Spring Snapshots 84 | https://repo.spring.io/snapshot 85 | 86 | true 87 | 88 | 89 | 90 | spring-milestones 91 | Spring Milestones 92 | https://repo.spring.io/milestone 93 | 94 | false 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /reactive/test/java/com/example/car/IntegrationTests.java: -------------------------------------------------------------------------------- 1 | package com.example.car; 2 | 3 | import com.example.car.domain.Car; 4 | import com.example.car.domain.CarRepository; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.data.mongodb.core.CollectionOptions; 12 | import org.springframework.data.mongodb.core.ReactiveMongoOperations; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | import org.springframework.test.web.reactive.server.WebTestClient; 15 | 16 | import static org.assertj.core.api.Assertions.assertThat; 17 | 18 | @RunWith(SpringRunner.class) 19 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 20 | public class IntegrationTests { 21 | 22 | @Autowired 23 | private WebTestClient webTestClient; 24 | 25 | @Autowired 26 | private CarRepository carRepository; 27 | 28 | @Autowired 29 | private ReactiveMongoOperations operations; 30 | 31 | @Before 32 | public void setUp() throws Exception { 33 | this.operations 34 | .createCollection(Car.class, CollectionOptions.empty().size(1024 * 1024).maxDocuments( 100).capped()) 35 | .then() 36 | .block(); 37 | 38 | this.carRepository 39 | .save(new Car("prius", "hybrid")) 40 | .then() 41 | .block(); 42 | } 43 | 44 | @Test 45 | public void getCar_WithName_ReturnsCar() { 46 | Car car = this.webTestClient.get().uri("/cars/{name}", "prius") 47 | .exchange().expectStatus().isOk() 48 | .expectBody(Car.class).returnResult().getResponseBody(); 49 | assertThat(car.getName()).isEqualTo("prius"); 50 | assertThat(car.getType()).isEqualTo("hybrid"); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /reactive/test/java/com/example/car/domain/CarRepositoryTests.java: -------------------------------------------------------------------------------- 1 | package com.example.car.domain; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import reactor.test.StepVerifier; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | 15 | @RunWith(SpringRunner.class) 16 | @DataMongoTest 17 | public class CarRepositoryTests { 18 | 19 | @Autowired 20 | private CarRepository carRepository; 21 | 22 | @Before 23 | public void setUp() throws Exception { 24 | this.carRepository.save(new Car("prius", "hybrid")) 25 | .then() 26 | .block(); 27 | } 28 | 29 | @After 30 | public void tearDown() throws Exception { 31 | carRepository.deleteAll() 32 | .then() 33 | .block(); 34 | } 35 | 36 | @Test 37 | public void findByName_returnsCar() { 38 | StepVerifier.create(carRepository.findByName("prius")) 39 | .consumeNextWith(car -> { 40 | assertThat(car.getName()).isEqualTo("prius"); 41 | assertThat(car.getType()).isEqualTo("hybrid"); 42 | }) 43 | .verifyComplete(); 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /reactive/test/java/com/example/car/web/CarControllerTests.java: -------------------------------------------------------------------------------- 1 | package com.example.car.web; 2 | 3 | import com.example.car.domain.Car; 4 | import com.example.car.domain.CarRepository; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import reactor.core.publisher.Mono; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; 11 | import org.springframework.boot.test.mock.mockito.MockBean; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | import org.springframework.test.web.reactive.server.WebTestClient; 14 | 15 | import static org.mockito.BDDMockito.given; 16 | 17 | @RunWith(SpringRunner.class) 18 | @WebFluxTest 19 | public class CarControllerTests { 20 | 21 | @MockBean 22 | private CarRepository carRepository; 23 | 24 | @Autowired 25 | private WebTestClient webTestClient; 26 | 27 | @Test 28 | public void getCar_WithName_returnsCar() throws Exception { 29 | Car car = new Car("prius", "hybrid"); 30 | given(carRepository.findByName("prius")).willReturn(Mono.just(car)); 31 | 32 | this.webTestClient.get().uri("/cars/{name}", "prius") 33 | .exchange().expectStatus().isOk() 34 | .expectBody() 35 | .jsonPath("name").isEqualTo("prius") 36 | .jsonPath("type").isEqualTo("hybrid"); 37 | } 38 | 39 | } 40 | --------------------------------------------------------------------------------