Skip to content

Commit b6a7f5d

Browse files
committed
Stake in the ground
1 parent 59048ae commit b6a7f5d

File tree

20 files changed

+445
-375
lines changed

20 files changed

+445
-375
lines changed

2/part1/src/main/java/com/greglturnquist/learningspringboot/ReactiveThymeleafConfig.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@
1515
*/
1616
package com.greglturnquist.learningspringboot;
1717

18+
import org.thymeleaf.spring5.SpringWebFluxTemplateEngine;
19+
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
20+
import org.thymeleaf.spring5.view.reactive.ThymeleafReactiveViewResolver;
21+
1822
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties;
1923
import org.springframework.boot.context.properties.EnableConfigurationProperties;
2024
import org.springframework.context.ApplicationContext;
2125
import org.springframework.context.annotation.Bean;
2226
import org.springframework.context.annotation.Configuration;
23-
import org.thymeleaf.spring5.SpringWebFluxTemplateEngine;
24-
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
25-
import org.thymeleaf.spring5.view.reactive.ThymeleafReactiveViewResolver;
27+
import org.springframework.context.annotation.Primary;
2628

2729
/**
2830
* @author Greg Turnquist
@@ -62,6 +64,7 @@ public SpringWebFluxTemplateEngine thymeleafTemplateEngine(SpringResourceTemplat
6264

6365
// tag::2[]
6466
@Bean
67+
@Primary
6568
public SpringResourceTemplateResolver thymeleafTemplateResolver(ApplicationContext applicationContext) {
6669

6770
final SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();

2/part2/build.gradle

+3-2
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ ext['thymeleaf.version'] = thymeleafVersion
4040
dependencies {
4141
// tag::netty[]
4242
compile('org.springframework.boot:spring-boot-starter-webflux') {
43-
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
43+
exclude group: 'org.springframework.boot',
44+
module: 'spring-boot-starter-reactor-netty'
4445
}
45-
compile('org.springframework.boot:spring-boot-starter-reactor-netty')
46+
compile('org.springframework.boot:spring-boot-starter-tomcat')
4647
// end::netty[]
4748
compile("org.thymeleaf:thymeleaf-spring5:${thymeleafVersion}")
4849
compile('org.projectlombok:lombok')

4/part1/src/test/java/com/greglturnquist/learningspringboot/EmbeddedImageRepositoryTests.java

+58-40
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,21 @@
1515
*/
1616
package com.greglturnquist.learningspringboot;
1717

18+
import static org.assertj.core.api.Assertions.*;
19+
20+
import java.util.ArrayList;
21+
1822
import org.junit.Before;
1923
import org.junit.Test;
2024
import org.junit.runner.RunWith;
25+
import reactor.core.publisher.Flux;
26+
import reactor.core.publisher.Mono;
27+
import reactor.test.StepVerifier;
28+
2129
import org.springframework.beans.factory.annotation.Autowired;
2230
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
31+
import org.springframework.data.mongodb.core.MongoOperations;
2332
import org.springframework.test.context.junit4.SpringRunner;
24-
import reactor.core.publisher.Mono;
25-
import java.time.Duration;
26-
import java.util.List;
27-
28-
import static org.assertj.core.api.Assertions.assertThat;
2933

3034
/**
3135
* @author Greg Turnquist
@@ -37,60 +41,74 @@ public class EmbeddedImageRepositoryTests {
3741

3842
@Autowired
3943
ImageRepository repository;
44+
45+
@Autowired
46+
MongoOperations operations;
4047
// end::1[]
4148

4249
// tag::2[]
50+
/**
51+
* To avoid {@code block()} calls, use blocking {@link MongoOperations} during setup.
52+
*/
4353
@Before
4454
public void setUp() {
45-
repository
46-
.deleteAll()
47-
.then(() -> Mono.when(
48-
repository.save(
49-
new Image("1",
50-
"learning-spring-boot-cover.jpg"))
51-
.log("initDatabase"),
52-
repository.save(
53-
new Image("2",
54-
"learning-spring-boot-2nd-edition-cover.jpg"))
55-
.log("initDatabase"),
56-
repository.save(
57-
new Image("3",
58-
"bazinga.png"))
59-
.log("initDatabase")
60-
))
61-
.then(() -> repository.findAll().collectList())
62-
.then(images -> {
63-
images.forEach(image ->
64-
System.out.println(image.toString()));
65-
return Mono.empty();
66-
})
67-
.block(Duration.ofSeconds(30));
55+
56+
operations.dropCollection(Image.class);
57+
58+
operations.insert(new Image("1",
59+
"learning-spring-boot-cover.jpg"));
60+
operations.insert(new Image("2",
61+
"learning-spring-boot-2nd-edition-cover.jpg"));
62+
operations.insert(new Image("3",
63+
"bazinga.png"));
64+
65+
operations.findAll(Image.class).forEach(image -> {
66+
System.out.println(image.toString());
67+
});
6868
}
6969
// end::2[]
7070

7171
// tag::3[]
7272
@Test
7373
public void findAllShouldWork() {
74-
List<Image> images = repository.findAll().collectList().block();
75-
76-
assertThat(images).hasSize(3);
77-
assertThat(images)
78-
.extracting(Image::getName)
79-
.contains(
80-
"learning-spring-boot-cover.jpg",
81-
"learning-spring-boot-2nd-edition-cover.jpg",
82-
"bazinga.png");
74+
Flux<Image> images = repository.findAll();
75+
76+
StepVerifier.create(images)
77+
.recordWith(ArrayList::new)
78+
.expectNextCount(3)
79+
.consumeRecordedWith(results -> {
80+
assertThat(results).hasSize(3);
81+
assertThat(results)
82+
.extracting(Image::getName)
83+
.contains(
84+
"learning-spring-boot-cover.jpg",
85+
"learning-spring-boot-2nd-edition-cover.jpg",
86+
"bazinga.png");
87+
})
88+
.expectComplete()
89+
.verify();
8390
}
8491
// end::3[]
8592

8693
// tag::4[]
8794
@Test
8895
public void findByNameShouldWork() {
89-
Image image = repository.findByName("bazinga.png").block();
96+
Mono<Image> image = repository.findByName("bazinga.png");
9097

91-
assertThat(image.getName()).isEqualTo("bazinga.png");
92-
assertThat(image.getId()).isEqualTo("3");
98+
StepVerifier.create(image)
99+
.expectNextMatches(results -> {
100+
assertThat(results.getName()).isEqualTo("bazinga.png");
101+
assertThat(results.getId()).isEqualTo("3");
102+
return true;
103+
});
93104
}
94105
// end::4[]
95106

107+
// tag::5[]
108+
@Test
109+
public void findAllShouldWork2() {
110+
// TODO: Remove
111+
}
112+
// end::5[]
113+
96114
}

4/part1/src/test/java/com/greglturnquist/learningspringboot/EndToEndTests.java

+9-7
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@
1515
*/
1616
package com.greglturnquist.learningspringboot;
1717

18+
import static org.assertj.core.api.Assertions.*;
19+
import static org.openqa.selenium.chrome.ChromeDriverService.*;
20+
21+
import java.io.File;
22+
import java.io.IOException;
23+
import java.net.MalformedURLException;
24+
1825
import org.junit.AfterClass;
1926
import org.junit.BeforeClass;
2027
import org.junit.Test;
@@ -23,16 +30,11 @@
2330
import org.openqa.selenium.OutputType;
2431
import org.openqa.selenium.chrome.ChromeDriver;
2532
import org.openqa.selenium.chrome.ChromeDriverService;
26-
import org.springframework.boot.context.embedded.LocalServerPort;
33+
2734
import org.springframework.boot.test.context.SpringBootTest;
35+
import org.springframework.boot.web.server.LocalServerPort;
2836
import org.springframework.test.context.junit4.SpringRunner;
2937
import org.springframework.util.FileCopyUtils;
30-
import java.io.File;
31-
import java.io.IOException;
32-
import java.net.MalformedURLException;
33-
34-
import static org.assertj.core.api.Assertions.*;
35-
import static org.openqa.selenium.chrome.ChromeDriverService.*;
3638

3739
/**
3840
* @author Greg Turnquist

4/part1/src/test/java/com/greglturnquist/learningspringboot/HomeControllerTests.java

+14-9
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,16 @@
1515
*/
1616
package com.greglturnquist.learningspringboot;
1717

18+
import static org.assertj.core.api.Assertions.*;
19+
import static org.mockito.BDDMockito.*;
20+
21+
import java.io.IOException;
22+
1823
import org.junit.Test;
1924
import org.junit.runner.RunWith;
25+
import reactor.core.publisher.Flux;
26+
import reactor.core.publisher.Mono;
27+
2028
import org.springframework.beans.factory.annotation.Autowired;
2129
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
2230
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
@@ -28,20 +36,15 @@
2836
import org.springframework.test.context.junit4.SpringRunner;
2937
import org.springframework.test.web.reactive.server.EntityExchangeResult;
3038
import org.springframework.test.web.reactive.server.WebTestClient;
31-
import reactor.core.publisher.Flux;
32-
import reactor.core.publisher.Mono;
33-
import java.io.IOException;
34-
35-
import static org.assertj.core.api.Assertions.*;
36-
import static org.mockito.BDDMockito.*;
3739

3840
/**
3941
* @author Greg Turnquist
4042
*/
4143
// tag::1[]
4244
@RunWith(SpringRunner.class)
4345
@WebFluxTest(controllers = HomeController.class)
44-
@Import({ReactiveThymeleafConfig.class, ThymeleafAutoConfiguration.class})
46+
@Import({ReactiveThymeleafConfig.class,
47+
ThymeleafAutoConfiguration.class})
4548
public class HomeControllerTests {
4649

4750
@Autowired
@@ -71,7 +74,8 @@ public void baseRouteShouldListAllImages() {
7174
verify(imageService).findAllImages();
7275
verifyNoMoreInteractions(imageService);
7376
assertThat(result.getResponseBody())
74-
.contains("<title>Learning Spring Boot: Spring-a-Gram</title>")
77+
.contains(
78+
"<title>Learning Spring Boot: Spring-a-Gram</title>")
7579
.contains("<a href=\"/images/alpha.png/raw\">")
7680
.contains("<a href=\"/images/bravo.png/raw\">");
7781
}
@@ -81,7 +85,8 @@ public void baseRouteShouldListAllImages() {
8185
@Test
8286
public void fetchingImageShouldWork() {
8387
given(imageService.findOneImage(any()))
84-
.willReturn(Mono.just(new ByteArrayResource("data".getBytes())));
88+
.willReturn(Mono.just(
89+
new ByteArrayResource("data".getBytes())));
8590

8691
webClient
8792
.get().uri("/images/alpha.png/raw")

4/part1/src/test/java/com/greglturnquist/learningspringboot/ImageServiceTests.java

+40-23
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,23 @@
1515
*/
1616
package com.greglturnquist.learningspringboot;
1717

18+
import static org.assertj.core.api.Assertions.tuple;
19+
import static org.assertj.core.api.BDDAssertions.then;
20+
import static org.mockito.BDDMockito.*;
21+
22+
import java.io.File;
23+
import java.io.IOException;
24+
import java.nio.file.Files;
25+
import java.nio.file.Paths;
26+
import java.util.ArrayList;
27+
1828
import org.junit.Before;
1929
import org.junit.Test;
2030
import org.junit.runner.RunWith;
31+
import reactor.core.publisher.Flux;
32+
import reactor.core.publisher.Mono;
33+
import reactor.test.StepVerifier;
34+
2135
import org.springframework.beans.factory.annotation.Autowired;
2236
import org.springframework.boot.test.context.SpringBootTest;
2337
import org.springframework.boot.test.mock.mockito.MockBean;
@@ -27,16 +41,6 @@
2741
import org.springframework.test.context.junit4.SpringRunner;
2842
import org.springframework.util.FileSystemUtils;
2943
import org.springframework.web.multipart.MultipartFile;
30-
import reactor.core.publisher.Flux;
31-
import reactor.core.publisher.Mono;
32-
import java.io.File;
33-
import java.io.IOException;
34-
import java.nio.file.Files;
35-
import java.nio.file.Paths;
36-
37-
import static org.assertj.core.api.Assertions.tuple;
38-
import static org.assertj.core.api.BDDAssertions.then;
39-
import static org.mockito.BDDMockito.*;
4044

4145
/**
4246
* @author Greg Turnquist
@@ -77,13 +81,19 @@ public void findAllShouldJustReturnTheFlux() {
7781

7882
// then
7983
then(images).isNotNull();
80-
then(images.collectList().block())
81-
.hasSize(2)
82-
.extracting(Image::getId, Image::getName)
83-
.contains(
84-
tuple("1", "alpha.jpg"),
85-
tuple("2", "bravo.jpg")
86-
);
84+
85+
StepVerifier.create(images)
86+
.recordWith(ArrayList::new)
87+
.expectNextCount(2)
88+
.consumeRecordedWith(results -> {
89+
then(results)
90+
.extracting(Image::getId, Image::getName)
91+
.contains(
92+
tuple("1", "alpha.jpg"),
93+
tuple("2", "bravo.jpg")
94+
);
95+
})
96+
.verifyComplete();
8797
}
8898

8999
@Test
@@ -93,10 +103,15 @@ public void findOneShouldReturnNotYetFetchedUrl() {
93103

94104
// then
95105
then(image).isNotNull();
96-
Resource resource = image.block();
97-
then(resource.getDescription()).isEqualTo("URL [file:upload-dir/alpha.jpg]");
98-
then(resource.exists()).isFalse();
99-
then(resource.getClass()).isEqualTo(UrlResource.class);
106+
107+
StepVerifier.create(image)
108+
.expectNextMatches(resource -> {
109+
then(resource.getDescription()).isEqualTo("URL [file:upload-dir/alpha.jpg]");
110+
then(resource.exists()).isFalse();
111+
then(resource.getClass()).isEqualTo(UrlResource.class);
112+
return true;
113+
})
114+
.verifyComplete();
100115
}
101116

102117
@Test
@@ -114,7 +129,8 @@ public void createImageShouldWork() {
114129
Mono<Void> done = imageService.createImage(Flux.just(file1, file2));
115130

116131
// then
117-
then(done.block()).isNull();
132+
StepVerifier.create(done)
133+
.verifyComplete();
118134
}
119135

120136
@Test
@@ -129,7 +145,8 @@ public void deleteImageShouldWork() {
129145
Mono<Void> done = imageService.deleteImage(imageName);
130146

131147
// then
132-
then(done.block()).isNull();
148+
StepVerifier.create(done)
149+
.verifyComplete();
133150
}
134151

135152
}

0 commit comments

Comments
 (0)