SlideShare a Scribd company logo
Whitebox testing of Spring Boot applications
About myself
Application Architect @Thomas
Cook
Tech Lead - Platformers team
9+ years Java
About myself
Application Architect @Thomas
Cook
Tech Lead - Platformers team
9+ years Java
*Very happy to leave an amazing teambuilding first to make it for a 5 AM flight back to Kyiv for this presentation
What is our current mission and vision in TC?
We are developing a flexible platform that will be able to make full use of CD
practices to improve time-to-market and be resilient enough to support a variety of
new markets.
Content
1. What we do in Thomas Cook
2. What problems we are facing with testing
3. Alternative frameworks - Spock and JUnit 5
4. Spring Boot testing
Mule -> Spring Boot
Mule -> Spring Boot
TestNG + JUnit 4
Our nice little monolith
...
...
...
Well, at least it’s Spring-based!
TestNG issues
● Test class lifecycle
TestNG issues
● Test class lifecycle:
@BeforeMethod
private void beforeMethod() {
objectUnderTest = null;
MockitoAnnotations.initMocks(this);
….
}
TestNG issues
● Test class lifecycle:
@BeforeMethod
private void beforeMethod() {
objectUnderTest = null;
MockitoAnnotations.initMocks(this);
….
}
*Funnily enough you can use the same lifecycle for JUnit 5 with @TestInstance:
enum Lifecycle
PER_CLASS, PER_METHOD;
TestNG issues
● A problem with Mockito related to the way Mockito used Reflection:
https://github.com/mockito/mockito/issues/810
https://github.com/mockito/mockito/pull/948
TestNG issues
● A problem with Mockito related to the way Mockito used Reflection:
https://github.com/mockito/mockito/issues/810
https://github.com/mockito/mockito/pull/948
Issues with JUnit 4
● Not possible to have several @RunWith
Issues with JUnit 4
● Not possible to have several @RunWith
For that reason a list of custom Rules was implemented on our side:
public class MockitoRule implements MethodRule {
@Override
public Statement apply(Statement base, FrameworkMethod frameworkMethod, Object test) {
settings.test = test;
Statement wrappedStatement = new MockitoInitializationStatement(base, settings);
wrappedStatement = new MockitoVerificationStatement(wrappedStatement, settings);
return wrappedStatement;
}
What are the alternatives?
Spock: Overview
Spock: based on JUnit runner
No hassle with the runner: What’s more it extends Junit runner so it can run by
the tools you used for your tests before.
@RunWith(Sputnik.class)
public abstract class Specification extends MockingApi
….
public class Sputnik extends Runner implements Filterable, Sortable
Spock: formal semantics
JUnit tests lack formal semantics
The number one reason for using Spock is to make your tests more readable.
Spock: test blocks
Spock: test blocks
Having them in your tests is mandatory.
Otherwise a piece of code like this will not complain:
def "CreateBooking"() {
whatever
}
Spock: test example
def "should fetch Bob and Alice without errors"() {
given:
def response =
mockMvc.perform(MockMvcRequestBuilders.get("/bookings/$id")).andReturn().response
def content = new JsonSlurper().parseText(response.contentAsString)
expect:
response.status == OK.value()
and:
content.passengerName == result
where:
id || result
'5' || "Bob"
'15' || "Alice"
}
Spock: Data Pipes
Spock: Data Pipes
Can be as advances as this:
Spock: @Shared fields
Objects stored into instance fields are not shared between feature methods. Instead, every feature
method gets its own object. This helps to isolate feature methods from each other, which is often a
desirable goal.
@Shared res = new VeryExpensiveResource()
Spock: error reporting
Nice and layered: Condition not satisfied:
content.passengerName == result
| | | |
| Bob | Bob1
| false
| 1 difference (75% similarity)
| Bob(-)
| Bob(1)
Condition not satisfied:
content.passengerName == result
| | | |
| Alice | Alice2
| false
| 1 difference (83% similarity)
| Alice(-)
| Alice(2)
Spock: parameterization is way better than in JUnit 4
There is a way to do it for JUnit, but it’s an external lib. Otherwise, it’s just too
verbose
Spock: Interactions
A way to express which method invocations are expected to occur:
then: "a rejection email is sent to the customer"
0 * emailService.sendConfirmation(sampleCustomer.getEmailAddress())
1 * emailService.sendRejection(sampleCustomer.getEmailAddress())
//Can also be:
(1..3) * subscriber.receive("hello") // between one and three calls (inclusive)
(1.._) * subscriber.receive("hello") // at least one call
(_..3) * subscriber.receive("hello") // at most three calls
Spock: Interactions - powerful matchers
1 * subscriber./r.*e/("hello") // a method whose name matches the given regular expression
// (here: method name starts with 'r' and ends in 'e')
1 * subscriber.receive(_) // any single argument (including null)
1 * subscriber.receive(*_) // any argument list (including the empty argument list)
1 * _._ // any method call on any mock object
1 * _ // shortcut for and preferred over the above
Spock: Drawbacks
A bit scary versioning:
Groovy: Drawbacks
If everything inside your test/ folder will be Groovy based there’s a good
chance you will want to have some TestUtils/TestBuilders there at some
point. And you will use Groovy for all that.
Groovy: Drawbacks
Groovy: With great power...
Groovy: Drawbacks
It’s similar to java, but there will still be a learning curve and some tricky cases.
My use case - copying one object into another based on SO:
https://stackoverflow.com/questions/9072307/copy-groovy-class-properties/9072974#9072974
Groovy: Drawbacks
My use case - copying one object into another:
https://stackoverflow.com/questions/46952475/copy-object-properties-to-another-object-in-groovy
Groovy: Drawbacks
Comments/Answers:
My use case - copying one object into another:
Groovy: Drawbacks
My use case - copying one object into another:
Comments/Answers:
JUnit 5: finally released!
JUnit 5: motivation
JUnit 5: module composition
JUnit 5 is composed of several different modules from three different sub-projects.
JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
JUnit 5: native support in Spring 5.0
Spring-boot version 1.5.9-RELEASE is based on Spring 4 and the
SpringExtension is only available since Spring 5.
JUnit 5: can run on top of JUnit 4
JUnit 5: reason for re-architecture
● JUnit 4 test discovery and execution were tightly coupled.
● JUnit 4 - java 5 compatible - that’s ridiculous!
JUnit 5: architectural diagram
JUnit 5: all interested parties
This substantially simplifies collaboration between:
● JUnit framework developers;
● Developers writing tests for their products;
● IDE developers;
● Build tool developers.
JUnit 5: powerful ExtendWith
Only one @RunWith but many @ExtendWith.
@ExtendWith(SpringExtension.class)
JUnit 5: asserts are never skipped
Assert are not skipped if one failed:
void getBooking() throws Exception {
String bob = mockMvc.perform(MockMvcRequestBuilders.get("/bookings/5"))
.andReturn().getResponse().getContentAsString();
ObjectMapper objectMapper = new ObjectMapper();
assertAll("Analyzing Bob's record",
() -> assertEquals("NotBob", objectMapper.readValue(bob, Booking.class).getPassengerName()),
() -> assertEquals("USA", objectMapper.readValue(bob, Booking.class).getDestination()),
() -> assertEquals(Double.valueOf(35), objectMapper.readValue(bob, Booking.class).getAge()));
}
JUnit 5: asserts are never skipped
Assert are not skipped if one failed:
void getBooking() throws Exception {
String bob = mockMvc.perform(MockMvcRequestBuilders.get("/bookings/5"))
.andReturn().getResponse().getContentAsString();
ObjectMapper objectMapper = new ObjectMapper();
assertAll("Analyzing Bob's record",
() -> assertEquals("NotBob", objectMapper.readValue(bob, Booking.class).getPassengerName()),
() -> assertEquals("USA", objectMapper.readValue(bob, Booking.class).getDestination()),
() -> assertEquals(Double.valueOf(35), objectMapper.readValue(bob, Booking.class).getAge()));
}
Fail
Fail
Pass
JUnit 5: asserts are never skipped
Will require fewer iterations to stabilize your code
JUnit 5: out-of-the-box support for Exceptions
@org.junit.jupiter.api.Test
void testException() {
Executable closureContainingCodeToTest = () -> {throw new ConcurrentModificationException();};
assertThrows(ConcurrentModificationException.class, closureContainingCodeToTest);
}
JUnit 5: Autowiring into a method
@org.junit.jupiter.api.Test
void getBooking(@Autowired MockMvc mockMvc) throws Exception {
String bob = mockMvc.perform(MockMvcRequestBuilders.get("/bookings/5"))
.andReturn().getResponse().getContentAsString();
JUnit 5: Autowiring into a method
No need to create loads of fields in your test class.
Inject what is needed to a specific test method.
JUnit 5: Support for @Nested classes
@DisplayName("A stack")
class TestingAStackDemo {
@Test
@DisplayName("is instantiated with new Stack()")
void isInstantiatedWithNew() {
...
}
@Nested
@DisplayName("when new")
class WhenNew {
...
}
Spring Boot Testing: Overview
Spring Boot BOM(?) specifies following test-related
dependencies:
● spring-boot-test
● spring-boot-test-autoconfigure
● spring-boot-starter-test
● solr-test-framework
● groovy-test
● groovy-testng
● hibernate-testing
● spring-batch-test
● spring-kafka-test
● spring-ldap-test
● spring-restdocs-webtestclient
● spring-ws-test
Spring Boot Testing: Overview
Spring Boot BOM(spring-boot-dependencies pom) specifies
following test-related dependencies:
● spring-boot-test
● spring-boot-test-autoconfigure
● spring-boot-starter-test
● solr-test-framework
● groovy-test
● groovy-testng
● hibernate-testing
● spring-batch-test
● spring-kafka-test
● spring-ldap-test
● spring-restdocs-webtestclient
● spring-ws-test
Spring Boot Testing: Overview
We will mainly focus on these ones:
● spring-boot-test
● spring-boot-test-autoconfigure
● spring-boot-starter-test
● solr-test-framework
● groovy-test
● groovy-testng
● hibernate-testing
● spring-batch-test
● spring-kafka-test
● spring-ldap-test
● spring-restdocs-webtestclient
● spring-ws-test
Spring Boot Testing: Overview
Only one test-specific starter:
Spring Test: Integration Testing
Spring’s integration testing support has the following primary goals:
● To manage Spring IoC container caching between test execution.
● To provide Dependency Injection of test fixture instances.
● To provide transaction management appropriate to integration testing.
● To supply Spring-specific base classes that assist developers in writing integration
tests.
Spring Test: how are transactions handled?
Your tests might run against a real database. It’s rare, but possible. We are talking
about Integration tests after all.
By default, the framework will create and roll back a transaction for each test.
If a test method deletes the contents of selected tables while running within the
transaction managed for the test, the transaction will rollback by default, and the
database will return to its state prior to execution of the test.
Spring Test: how are transactions handled?
Your tests might run against a real database. It’s rare, but possible. We are talking
about Integration tests after all.
By default, the framework will create and roll back a transaction for each test.
If a test method deletes the contents of selected tables while running within the
transaction managed for the test, the transaction will rollback by default, and the
database will return to its state prior to execution of the test.
More flexibility is available via @Commit and @Rollback
Spring Test: how are transactions handled?
Your tests might run against a real database. It’s rare, but possible. We are talking
about Integration tests after all.
By default, the framework will create and roll back a transaction for each test.
If a test method deletes the contents of selected tables while running within the
transaction managed for the test, the transaction will rollback by default, and the
database will return to its state prior to execution of the test.
Not always that straightforward. Probably depends on implicit commits and
DB engines. Will also only work for MOCK transport.
Spring Test: main actors
TestContextManager TestContext
TestExecutionListeners
Spring Test: TestContextManager
Main entry point into Spring test related functionality
Spring
Test
Context
Spring Test: factories for ExecutionListener
Spring Test: factories for ExecutionListener
Will scan your test class, look at its annotations and add its logic accordingly.
Spring Test: Reactive support
The package org.springframework.mock.http.server.reactive contains mock
implementations of ServerHttpRequest and ServerHttpResponse for use in
WebFlux applications.
The WebTestClient builds on the mock request and response to provide support
for testing WebFlux applications without an HTTP server.
Spring Test: static cache
Test suites and forked processes
The Spring TestContext framework stores application contexts in a static cache.
This means that the context is literally stored in a static variable. In other words, if
tests execute in separate processes the static cache will be cleared between each
test execution, and this will effectively disable the caching mechanism.
Spring Boot + Spock: pom file
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<configuration>
<testSources>
<testSource>
<directory>${project.basedir}/src/test/java</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</testSource>
</testSources>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compileTests</goal>
</goals>
</execution>
</executions>
</plugin>
Spring Boot + Spock: pom file
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.1-groovy-2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<version>1.1-groovy-2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.13</version>
</dependency>
Spring Boot + Spock: pom file
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.1-groovy-2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-spring</artifactId>
<version>1.1-groovy-2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.4.13</version>
</dependency>
Default scope
Spring Boot + Spock
Integration with Spock: Detached mocks via the DetachedMockFactory and
SpockMockFactoryBean classes.
class TestConfigurationForSpock {
private final detachedMockFactory = new DetachedMockFactory()
@Bean
BookingService bookingService() {
detachedMockFactory.Mock(BookingService);
}
}
Then just use: @Import(TestConfigurationForSpock)
Spring Boot + JUnit 5
Will need to include an additional library to use JUnit 5 with Spring Framework 4.3
Spring Boot + JUnit 5
There’s nothing at all Spock specific in spring-test, but you can find junit.jupiter is
there:
Spring Boot + JUnit 5
Be careful with your surefire version:
Spring Boot + JUnit 5: pom file
<dependency>
<artifactId>junit-platform-launcher</artifactId>
</dependency>
<dependency>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
<dependency>
<artifactId>junit-vintage-engine</artifactId>
</dependency>
<dependency>
<artifactId>junit-jupiter-api</artifactId>
</dependency>
<dependency>
<artifactId>junit-jupiter-params</artifactId>
</dependency>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
<configuration>
<includes>
<include>**/Test*.java</include>
<include>**/*Test.java</include>
<include>**/*Tests.java</include>
<include>**/*TestCase.java</include>
</includes>
</configuration>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>${junit.platform.version}</version>
</dependency>
</dependencies>
</plugin>
Spock vs JUnit 5: integration with Spring
Both frameworks provide a class with exact same name: SpringExtension.
However, the name is the only thing they have in common.
Spock vs JUnit 5: integration with Spring
SpringExtension
Spock JUnit 5
Tries to find any Spring-specific annotation on a test
class(spec): ContentHierarchy, BootstrapWith,
ContextConfiguration.
Using Spring-provided MetaAnnotaionUtils, so that it
can traverse class hierarchy.
Spring Test SpringExtention implements all possible
JUnit 5 callbacks(.e.g.: BeforeAllCallback,
AfterAllCallback)
If found, creates a TestContextManager and
delegate to it.
Will either get TestContextManager from a store of
create one.
Attaches Spock-specific listener for managing
Mocks:
testContext.setAttribute(MOCKED_BEANS_LIST,
mockedBeans);
Will wrap TestContextManager calls and delegate to
it. E.g.:
public void beforeAll(ExtensionContext context) {
getTestContextManager(context).beforeTestClass();
Spring Boot: autoconfigure slicing
Auto-configured tests
The spring-boot-test-autoconfigure module includes a number of annotations that can be used to
automatically configure different ‘slices’ of your app for testing purposes.
Examples:
● @WebMvcTest
● @JsonTest
● @DataJpaTest
● @JdbcTest
● @DataMongoTest
● ...
Spring Boot: autoconfigure slicing
@*Test would normally contain several @AutoConfigure* annotations:
For example:
...
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(DataJpaTypeExcludeFilter.class)
@Transactional
@AutoConfigureCache
@AutoConfigureDataJpa
@AutoConfigureTestDatabase
@AutoConfigureTestEntityManager
@ImportAutoConfiguration
public @interface DataJpaTest
Spring Boot: autoconfigure slicing
To tweak @*Test mechanism, you can use a corresponding @AutoConfigure*
annotation.
For example:
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
public class ExampleRepositoryTests {
// ...
}
Spring Boot: autoconfigure slicing
Have you noticed this relatively unremarkable meta annotation:
@OverrideAutoConfiguration(enabled = false)
It will effectively set:
spring.boot.enableautoconfiguration=false
via AbstractTestContextBootstrapper
String Boot: Bootstrapping
@BootstrapWith is used on @SpringBootTest, for example.
String Boot: Bootstrapping
@BootstrapWith is used on @SpringBootTest, for example.
● Aware of Spring Boot
application structure;
● Helps SpringBootTest;
String Boot: Bootstrapping
As TestContextManager is the main entry point for test frameworks all they need
is to create one:
public TestContextManager(Class<?> testClass) {
this(BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.createBootstrapContext(testClass)));
}
Spring Boot: Slicing
Do not litter the application’s main class with configuration settings that are are
specific to a particular area of its functionality.
Extract them into specific @Configuration instead. Otherwise they will be picked
up by all slice tests, which might not be what you want:
@SpringBootApplication
@EnableBatchProcessing - DO NOT DO IT THIS WAY
public class SampleApplication { ... }
Spring Boot: Custom component scanning
Another source of confusion is classpath scanning. Assume that, while you
structured your code in a sensible way, you need to scan an additional package.
Your application may resemble the following code:
@SpringBootApplication
@ComponentScan({ "com.example.app", "org.acme.another" }) - ALSO BAD
public class SampleApplication { ... }
This effectively overrides the default component scan directive with the side effect
of scanning those two packages regardless of the slice that you’ve chosen.
Spring Boot: TypeExcludeFilter
AutoConfigurationExcludeFilter - tells Spring Boot to exclude scanning
autoconfigurations. To use SpringFactoriesLoader instead.
TypeExcludeFilter - is an interesting case. While it’s in spring-boot jar, the doc
actually says: primarily used internally to support spring-boot-test.
Spring Boot: TypeExcludeFilter
Pivotal cares about your application’s tests so much, they put a test-specific
logic into their main Spring Boot module!
Spring Boot: TypeExcludeFilter
Indeed, all subclasses seem to be coming from spring-boot-test-autoconfigure and
spring-boot-test:
Spring Boot: TypeExcludeFilter
What a specific test filter effectively does is:
1. Loads a corresponding annotation. E.g.: WebMvcTest for
WebMvcTypeExcludeFilter, DataJpaTest for DataJpaTypeExcludeFilter;
2. Inside *ExcludeFilter add specific annotations for which you want to enable
ComponentScan. For most *ExcludeFilters it is not required, however. They
will simply rely on SpringFactoriesLoader
@TestConfiguration :
● Unlike a nested @Configuration class which would be used instead of a your
application’s primary configuration, a nested @TestConfiguration class will
be used in addition to your application’s primary configuration;
● When placed on a top-level class, @TestConfiguration indicates that classes
in src/test/java should not be picked up by scanning. Use explicit @Import to
use them.
Spring Boot: overriding configurations
Spring Boot: Mocking and spying beans
For example, you may have a facade over some remote service that’s unavailable
during development.
Spring Boot includes a @MockBean annotation that can be used to define a
Mockito mock for a bean inside your ApplicationContext.
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyTests {
@MockBean
private RemoteService remoteService;
Spring Boot: AutoConfigureMockMvc
There is an option to not start the server at all, but test only the layer below that,
where Spring handles the incoming HTTP request and hands it off to your
controller. That way, almost the full stack is used, and your code will be called
exactly the same way as if it was processing a real HTTP request, but without the
cost of starting the server. To do that we will use Spring’s MockMvc, and we can
ask for that to be injected for us by using the @AutoConfigureMockMvc annotation
on the test case.
https://spring.io/guides/gs/testing-web/
Spring Boot: WebMvcTest
@WebMvcTest
Only web layer is instantiated, not the whole context.
Often @WebMvcTest will be limited to a single controller and used in combination
with @MockBean to provide mock implementations for required collaborators.
Spring Boot: WebMvcTest vs AutoConfigureMockMvc vs
SpringBootTest
The main difference is inside META-INF/spring.factories:
# AutoConfigureMockMvc auto-configuration imports
org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc=
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration,
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityAutoConfiguration,
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration,
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration
You’ll notice that WebMvcTest has also a @ImportAutoConfiguration *, but there’s
no entry in spring.factories for it.
https://spring.io/blog/2016/08/30/custom-test-slice-with-spring-boot-1-4
Spring Boot: WebMvcTest vs AutoConfigureMockMvc vs
SpringBootTest
The main difference is inside META-INF/spring.factories:
# AutoConfigureMockMvc auto-configuration imports
org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc=
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration,
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityAutoConfiguration,
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration,
org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration
You’ll notice that WebMvcTest has also a @ImportAutoConfiguration *, but there’s
no entry in spring.factories for it.
However it has an exclude filter to reduce the amount of scanned objects.
Spring Boot: SpringBootTest MOCK WebEnvironment
Embedded servlet containers are not started when using this attribute. Can be
used in conjunction with @AutoConfigureMockMvc for MockMvc-based testing of
your application.
Spring Boot: SpringBootTest
RANDOM_PORT/DEFINED_PORT WebEnvironment
A test like this will run perfectly fine with real HTTP transport:
@SpringBootTest(classes = RamlBasedProducerApplication, webEnvironment =
SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@OverrideAutoConfiguration(enabled = true)
class BookingServiceImplSpockTest extends Specification {
@LocalServerPort
private int port;
@Autowired
MockMvc mockMvc;
Spring will inject different ServletContexts into MockMvc depending on webEnv.
Spring Boot: Test utilities
● EnvironmentTestUtils(addEnvironment(env, "org=Spring", "name=Boot"))
● TestRestTemplate(behave in a test-friendly way by not throwing exceptions
on server-side errors)
● MockRestServiceServer(part of Spring Test)
Whitebox testing of Spring Boot applications
Ad

More Related Content

What's hot (20)

React new features and intro to Hooks
React new features and intro to HooksReact new features and intro to Hooks
React new features and intro to Hooks
Soluto
 
Java 8 Lambda Expressions
Java 8 Lambda ExpressionsJava 8 Lambda Expressions
Java 8 Lambda Expressions
Scott Leberknight
 
Hibernate Presentation
Hibernate  PresentationHibernate  Presentation
Hibernate Presentation
guest11106b
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
José Paumard
 
ES6 presentation
ES6 presentationES6 presentation
ES6 presentation
ritika1
 
Getting started with typescript
Getting started with typescriptGetting started with typescript
Getting started with typescript
C...L, NESPRESSO, WAFAASSURANCE, SOFRECOM ORANGE
 
Introduction to kotlin
Introduction to kotlinIntroduction to kotlin
Introduction to kotlin
Shaul Rosenzwieg
 
50 nouvelles choses que l'on peut faire avec Java 8
50 nouvelles choses que l'on peut faire avec Java 850 nouvelles choses que l'on peut faire avec Java 8
50 nouvelles choses que l'on peut faire avec Java 8
José Paumard
 
Java 17
Java 17Java 17
Java 17
Mutlu Okuducu
 
Fundamental JavaScript [UTC, March 2014]
Fundamental JavaScript [UTC, March 2014]Fundamental JavaScript [UTC, March 2014]
Fundamental JavaScript [UTC, March 2014]
Aaron Gustafson
 
Gradle Introduction
Gradle IntroductionGradle Introduction
Gradle Introduction
Dmitry Buzdin
 
Spring Core
Spring CoreSpring Core
Spring Core
Pushan Bhattacharya
 
Core java Essentials
Core java EssentialsCore java Essentials
Core java Essentials
SRM Institute of Science & Technology, Tiruchirappalli
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
LivePerson
 
Deep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UKDeep Dive Java 17 Devoxx UK
Deep Dive Java 17 Devoxx UK
José Paumard
 
Rxjs ppt
Rxjs pptRxjs ppt
Rxjs ppt
Christoffer Noring
 
The virtual DOM and how react uses it internally
The virtual DOM and how react uses it internallyThe virtual DOM and how react uses it internally
The virtual DOM and how react uses it internally
Clóvis Neto
 
ES2015 / ES6: Basics of modern Javascript
ES2015 / ES6: Basics of modern JavascriptES2015 / ES6: Basics of modern Javascript
ES2015 / ES6: Basics of modern Javascript
Wojciech Dzikowski
 
React js
React jsReact js
React js
Oswald Campesato
 
Angular - Chapter 4 - Data and Event Handling
 Angular - Chapter 4 - Data and Event Handling Angular - Chapter 4 - Data and Event Handling
Angular - Chapter 4 - Data and Event Handling
WebStackAcademy
 

Similar to Whitebox testing of Spring Boot applications (20)

Testing Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 worldTesting Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 world
Yura Nosenko
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock Framework
Eugene Dvorkin
 
Cool JVM Tools to Help You Test
Cool JVM Tools to Help You TestCool JVM Tools to Help You Test
Cool JVM Tools to Help You Test
Schalk Cronjé
 
Spock Framework
Spock FrameworkSpock Framework
Spock Framework
Леонид Ставила
 
Unit Testing in iOS
Unit Testing in iOSUnit Testing in iOS
Unit Testing in iOS
Long Weekend LLC
 
RoboSpock Poznań ADG 2016
RoboSpock Poznań ADG 2016RoboSpock Poznań ADG 2016
RoboSpock Poznań ADG 2016
Przemek Jakubczyk
 
RoboSpock
RoboSpockRoboSpock
RoboSpock
Przemek Jakubczyk
 
Spock
SpockSpock
Spock
Evgeny Borisov
 
Using the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM DevelopmentUsing the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM Development
Schalk Cronjé
 
Junit_.pptx
Junit_.pptxJunit_.pptx
Junit_.pptx
Suman Sourav
 
Google mock training
Google mock trainingGoogle mock training
Google mock training
Thierry Gayet
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMock
Ying Zhang
 
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionCool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Schalk Cronjé
 
JavaProgrammingForBeginners-Presentation.pdf
JavaProgrammingForBeginners-Presentation.pdfJavaProgrammingForBeginners-Presentation.pdf
JavaProgrammingForBeginners-Presentation.pdf
Sathwika7
 
An Introduction to Gradle for Java Developers
An Introduction to Gradle for Java DevelopersAn Introduction to Gradle for Java Developers
An Introduction to Gradle for Java Developers
Kostas Saidis
 
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
Ortus Solutions, Corp
 
GeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testingGeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testing
Jakub Marchwicki
 
JavaScript Miller Columns
JavaScript Miller ColumnsJavaScript Miller Columns
JavaScript Miller Columns
Jonathan Fine
 
Greach 2015 Spock workshop
Greach 2015 Spock workshopGreach 2015 Spock workshop
Greach 2015 Spock workshop
Fernando Redondo Ramírez
 
Boosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with GroovyBoosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with Groovy
James Williams
 
Testing Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 worldTesting Spring Boot application in post-JUnit 4 world
Testing Spring Boot application in post-JUnit 4 world
Yura Nosenko
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock Framework
Eugene Dvorkin
 
Cool JVM Tools to Help You Test
Cool JVM Tools to Help You TestCool JVM Tools to Help You Test
Cool JVM Tools to Help You Test
Schalk Cronjé
 
Using the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM DevelopmentUsing the Groovy Ecosystem for Rapid JVM Development
Using the Groovy Ecosystem for Rapid JVM Development
Schalk Cronjé
 
Google mock training
Google mock trainingGoogle mock training
Google mock training
Thierry Gayet
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMock
Ying Zhang
 
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers VersionCool Jvm Tools to Help you Test - Aylesbury Testers Version
Cool Jvm Tools to Help you Test - Aylesbury Testers Version
Schalk Cronjé
 
JavaProgrammingForBeginners-Presentation.pdf
JavaProgrammingForBeginners-Presentation.pdfJavaProgrammingForBeginners-Presentation.pdf
JavaProgrammingForBeginners-Presentation.pdf
Sathwika7
 
An Introduction to Gradle for Java Developers
An Introduction to Gradle for Java DevelopersAn Introduction to Gradle for Java Developers
An Introduction to Gradle for Java Developers
Kostas Saidis
 
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
North Virginia Coldfusion User Group Meetup - Testbox - July 19th 2017
Ortus Solutions, Corp
 
GeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testingGeeCON 2012 hurdle run through ejb testing
GeeCON 2012 hurdle run through ejb testing
Jakub Marchwicki
 
JavaScript Miller Columns
JavaScript Miller ColumnsJavaScript Miller Columns
JavaScript Miller Columns
Jonathan Fine
 
Boosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with GroovyBoosting Your Testing Productivity with Groovy
Boosting Your Testing Productivity with Groovy
James Williams
 
Ad

Recently uploaded (20)

The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
PDF Reader Pro Crack Latest Version FREE Download 2025
PDF Reader Pro Crack Latest Version FREE Download 2025PDF Reader Pro Crack Latest Version FREE Download 2025
PDF Reader Pro Crack Latest Version FREE Download 2025
mu394968
 
Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025
mu394968
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRYLEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
NidaFarooq10
 
Top 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docxTop 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docx
Portli
 
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage DashboardsAdobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
BradBedford3
 
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
Egor Kaleynik
 
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
AxisTechnolabs
 
EASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License CodeEASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License Code
aneelaramzan63
 
Maxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINKMaxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINK
younisnoman75
 
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Orangescrum
 
Automation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath CertificateAutomation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath Certificate
VICTOR MAESTRE RAMIREZ
 
How can one start with crypto wallet development.pptx
How can one start with crypto wallet development.pptxHow can one start with crypto wallet development.pptx
How can one start with crypto wallet development.pptx
laravinson24
 
Download Wondershare Filmora Crack [2025] With Latest
Download Wondershare Filmora Crack [2025] With LatestDownload Wondershare Filmora Crack [2025] With Latest
Download Wondershare Filmora Crack [2025] With Latest
tahirabibi60507
 
Adobe Lightroom Classic Crack FREE Latest link 2025
Adobe Lightroom Classic Crack FREE Latest link 2025Adobe Lightroom Classic Crack FREE Latest link 2025
Adobe Lightroom Classic Crack FREE Latest link 2025
kashifyounis067
 
Pixologic ZBrush Crack Plus Activation Key [Latest 2025] New Version
Pixologic ZBrush Crack Plus Activation Key [Latest 2025] New VersionPixologic ZBrush Crack Plus Activation Key [Latest 2025] New Version
Pixologic ZBrush Crack Plus Activation Key [Latest 2025] New Version
saimabibi60507
 
Adobe After Effects Crack FREE FRESH version 2025
Adobe After Effects Crack FREE FRESH version 2025Adobe After Effects Crack FREE FRESH version 2025
Adobe After Effects Crack FREE FRESH version 2025
kashifyounis067
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025
kashifyounis067
 
The Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdfThe Significance of Hardware in Information Systems.pdf
The Significance of Hardware in Information Systems.pdf
drewplanas10
 
PDF Reader Pro Crack Latest Version FREE Download 2025
PDF Reader Pro Crack Latest Version FREE Download 2025PDF Reader Pro Crack Latest Version FREE Download 2025
PDF Reader Pro Crack Latest Version FREE Download 2025
mu394968
 
Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025Avast Premium Security Crack FREE Latest Version 2025
Avast Premium Security Crack FREE Latest Version 2025
mu394968
 
WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)WinRAR Crack for Windows (100% Working 2025)
WinRAR Crack for Windows (100% Working 2025)
sh607827
 
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRYLEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
LEARN SEO AND INCREASE YOUR KNOWLDGE IN SOFTWARE INDUSTRY
NidaFarooq10
 
Top 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docxTop 10 Client Portal Software Solutions for 2025.docx
Top 10 Client Portal Software Solutions for 2025.docx
Portli
 
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage DashboardsAdobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
Adobe Marketo Engage Champion Deep Dive - SFDC CRM Synch V2 & Usage Dashboards
BradBedford3
 
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
How Valletta helped healthcare SaaS to transform QA and compliance to grow wi...
Egor Kaleynik
 
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
Interactive odoo dashboards for sales, CRM , Inventory, Invoice, Purchase, Pr...
AxisTechnolabs
 
EASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License CodeEASEUS Partition Master Crack + License Code
EASEUS Partition Master Crack + License Code
aneelaramzan63
 
Maxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINKMaxon CINEMA 4D 2025 Crack FREE Download LINK
Maxon CINEMA 4D 2025 Crack FREE Download LINK
younisnoman75
 
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025Why Orangescrum Is a Game Changer for Construction Companies in 2025
Why Orangescrum Is a Game Changer for Construction Companies in 2025
Orangescrum
 
Automation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath CertificateAutomation Techniques in RPA - UiPath Certificate
Automation Techniques in RPA - UiPath Certificate
VICTOR MAESTRE RAMIREZ
 
How can one start with crypto wallet development.pptx
How can one start with crypto wallet development.pptxHow can one start with crypto wallet development.pptx
How can one start with crypto wallet development.pptx
laravinson24
 
Download Wondershare Filmora Crack [2025] With Latest
Download Wondershare Filmora Crack [2025] With LatestDownload Wondershare Filmora Crack [2025] With Latest
Download Wondershare Filmora Crack [2025] With Latest
tahirabibi60507
 
Adobe Lightroom Classic Crack FREE Latest link 2025
Adobe Lightroom Classic Crack FREE Latest link 2025Adobe Lightroom Classic Crack FREE Latest link 2025
Adobe Lightroom Classic Crack FREE Latest link 2025
kashifyounis067
 
Pixologic ZBrush Crack Plus Activation Key [Latest 2025] New Version
Pixologic ZBrush Crack Plus Activation Key [Latest 2025] New VersionPixologic ZBrush Crack Plus Activation Key [Latest 2025] New Version
Pixologic ZBrush Crack Plus Activation Key [Latest 2025] New Version
saimabibi60507
 
Adobe After Effects Crack FREE FRESH version 2025
Adobe After Effects Crack FREE FRESH version 2025Adobe After Effects Crack FREE FRESH version 2025
Adobe After Effects Crack FREE FRESH version 2025
kashifyounis067
 
Adobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest VersionAdobe Illustrator Crack FREE Download 2025 Latest Version
Adobe Illustrator Crack FREE Download 2025 Latest Version
kashifyounis067
 
Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025Adobe Master Collection CC Crack Advance Version 2025
Adobe Master Collection CC Crack Advance Version 2025
kashifyounis067
 
Ad

Whitebox testing of Spring Boot applications

  • 1. Whitebox testing of Spring Boot applications
  • 2. About myself Application Architect @Thomas Cook Tech Lead - Platformers team 9+ years Java
  • 3. About myself Application Architect @Thomas Cook Tech Lead - Platformers team 9+ years Java *Very happy to leave an amazing teambuilding first to make it for a 5 AM flight back to Kyiv for this presentation
  • 4. What is our current mission and vision in TC? We are developing a flexible platform that will be able to make full use of CD practices to improve time-to-market and be resilient enough to support a variety of new markets.
  • 5. Content 1. What we do in Thomas Cook 2. What problems we are facing with testing 3. Alternative frameworks - Spock and JUnit 5 4. Spring Boot testing
  • 7. Mule -> Spring Boot TestNG + JUnit 4
  • 8. Our nice little monolith
  • 9. ...
  • 10. ...
  • 11. ...
  • 12. Well, at least it’s Spring-based!
  • 13. TestNG issues ● Test class lifecycle
  • 14. TestNG issues ● Test class lifecycle: @BeforeMethod private void beforeMethod() { objectUnderTest = null; MockitoAnnotations.initMocks(this); …. }
  • 15. TestNG issues ● Test class lifecycle: @BeforeMethod private void beforeMethod() { objectUnderTest = null; MockitoAnnotations.initMocks(this); …. } *Funnily enough you can use the same lifecycle for JUnit 5 with @TestInstance: enum Lifecycle PER_CLASS, PER_METHOD;
  • 16. TestNG issues ● A problem with Mockito related to the way Mockito used Reflection: https://github.com/mockito/mockito/issues/810 https://github.com/mockito/mockito/pull/948
  • 17. TestNG issues ● A problem with Mockito related to the way Mockito used Reflection: https://github.com/mockito/mockito/issues/810 https://github.com/mockito/mockito/pull/948
  • 18. Issues with JUnit 4 ● Not possible to have several @RunWith
  • 19. Issues with JUnit 4 ● Not possible to have several @RunWith For that reason a list of custom Rules was implemented on our side: public class MockitoRule implements MethodRule { @Override public Statement apply(Statement base, FrameworkMethod frameworkMethod, Object test) { settings.test = test; Statement wrappedStatement = new MockitoInitializationStatement(base, settings); wrappedStatement = new MockitoVerificationStatement(wrappedStatement, settings); return wrappedStatement; }
  • 20. What are the alternatives?
  • 22. Spock: based on JUnit runner No hassle with the runner: What’s more it extends Junit runner so it can run by the tools you used for your tests before. @RunWith(Sputnik.class) public abstract class Specification extends MockingApi …. public class Sputnik extends Runner implements Filterable, Sortable
  • 23. Spock: formal semantics JUnit tests lack formal semantics The number one reason for using Spock is to make your tests more readable.
  • 25. Spock: test blocks Having them in your tests is mandatory. Otherwise a piece of code like this will not complain: def "CreateBooking"() { whatever }
  • 26. Spock: test example def "should fetch Bob and Alice without errors"() { given: def response = mockMvc.perform(MockMvcRequestBuilders.get("/bookings/$id")).andReturn().response def content = new JsonSlurper().parseText(response.contentAsString) expect: response.status == OK.value() and: content.passengerName == result where: id || result '5' || "Bob" '15' || "Alice" }
  • 28. Spock: Data Pipes Can be as advances as this:
  • 29. Spock: @Shared fields Objects stored into instance fields are not shared between feature methods. Instead, every feature method gets its own object. This helps to isolate feature methods from each other, which is often a desirable goal. @Shared res = new VeryExpensiveResource()
  • 30. Spock: error reporting Nice and layered: Condition not satisfied: content.passengerName == result | | | | | Bob | Bob1 | false | 1 difference (75% similarity) | Bob(-) | Bob(1) Condition not satisfied: content.passengerName == result | | | | | Alice | Alice2 | false | 1 difference (83% similarity) | Alice(-) | Alice(2)
  • 31. Spock: parameterization is way better than in JUnit 4 There is a way to do it for JUnit, but it’s an external lib. Otherwise, it’s just too verbose
  • 32. Spock: Interactions A way to express which method invocations are expected to occur: then: "a rejection email is sent to the customer" 0 * emailService.sendConfirmation(sampleCustomer.getEmailAddress()) 1 * emailService.sendRejection(sampleCustomer.getEmailAddress()) //Can also be: (1..3) * subscriber.receive("hello") // between one and three calls (inclusive) (1.._) * subscriber.receive("hello") // at least one call (_..3) * subscriber.receive("hello") // at most three calls
  • 33. Spock: Interactions - powerful matchers 1 * subscriber./r.*e/("hello") // a method whose name matches the given regular expression // (here: method name starts with 'r' and ends in 'e') 1 * subscriber.receive(_) // any single argument (including null) 1 * subscriber.receive(*_) // any argument list (including the empty argument list) 1 * _._ // any method call on any mock object 1 * _ // shortcut for and preferred over the above
  • 34. Spock: Drawbacks A bit scary versioning:
  • 35. Groovy: Drawbacks If everything inside your test/ folder will be Groovy based there’s a good chance you will want to have some TestUtils/TestBuilders there at some point. And you will use Groovy for all that.
  • 37. Groovy: Drawbacks It’s similar to java, but there will still be a learning curve and some tricky cases. My use case - copying one object into another based on SO: https://stackoverflow.com/questions/9072307/copy-groovy-class-properties/9072974#9072974
  • 38. Groovy: Drawbacks My use case - copying one object into another: https://stackoverflow.com/questions/46952475/copy-object-properties-to-another-object-in-groovy
  • 39. Groovy: Drawbacks Comments/Answers: My use case - copying one object into another:
  • 40. Groovy: Drawbacks My use case - copying one object into another: Comments/Answers:
  • 41. JUnit 5: finally released!
  • 43. JUnit 5: module composition JUnit 5 is composed of several different modules from three different sub-projects. JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
  • 44. JUnit 5: native support in Spring 5.0 Spring-boot version 1.5.9-RELEASE is based on Spring 4 and the SpringExtension is only available since Spring 5.
  • 45. JUnit 5: can run on top of JUnit 4
  • 46. JUnit 5: reason for re-architecture ● JUnit 4 test discovery and execution were tightly coupled. ● JUnit 4 - java 5 compatible - that’s ridiculous!
  • 48. JUnit 5: all interested parties This substantially simplifies collaboration between: ● JUnit framework developers; ● Developers writing tests for their products; ● IDE developers; ● Build tool developers.
  • 49. JUnit 5: powerful ExtendWith Only one @RunWith but many @ExtendWith. @ExtendWith(SpringExtension.class)
  • 50. JUnit 5: asserts are never skipped Assert are not skipped if one failed: void getBooking() throws Exception { String bob = mockMvc.perform(MockMvcRequestBuilders.get("/bookings/5")) .andReturn().getResponse().getContentAsString(); ObjectMapper objectMapper = new ObjectMapper(); assertAll("Analyzing Bob's record", () -> assertEquals("NotBob", objectMapper.readValue(bob, Booking.class).getPassengerName()), () -> assertEquals("USA", objectMapper.readValue(bob, Booking.class).getDestination()), () -> assertEquals(Double.valueOf(35), objectMapper.readValue(bob, Booking.class).getAge())); }
  • 51. JUnit 5: asserts are never skipped Assert are not skipped if one failed: void getBooking() throws Exception { String bob = mockMvc.perform(MockMvcRequestBuilders.get("/bookings/5")) .andReturn().getResponse().getContentAsString(); ObjectMapper objectMapper = new ObjectMapper(); assertAll("Analyzing Bob's record", () -> assertEquals("NotBob", objectMapper.readValue(bob, Booking.class).getPassengerName()), () -> assertEquals("USA", objectMapper.readValue(bob, Booking.class).getDestination()), () -> assertEquals(Double.valueOf(35), objectMapper.readValue(bob, Booking.class).getAge())); } Fail Fail Pass
  • 52. JUnit 5: asserts are never skipped Will require fewer iterations to stabilize your code
  • 53. JUnit 5: out-of-the-box support for Exceptions @org.junit.jupiter.api.Test void testException() { Executable closureContainingCodeToTest = () -> {throw new ConcurrentModificationException();}; assertThrows(ConcurrentModificationException.class, closureContainingCodeToTest); }
  • 54. JUnit 5: Autowiring into a method @org.junit.jupiter.api.Test void getBooking(@Autowired MockMvc mockMvc) throws Exception { String bob = mockMvc.perform(MockMvcRequestBuilders.get("/bookings/5")) .andReturn().getResponse().getContentAsString();
  • 55. JUnit 5: Autowiring into a method No need to create loads of fields in your test class. Inject what is needed to a specific test method.
  • 56. JUnit 5: Support for @Nested classes @DisplayName("A stack") class TestingAStackDemo { @Test @DisplayName("is instantiated with new Stack()") void isInstantiatedWithNew() { ... } @Nested @DisplayName("when new") class WhenNew { ... }
  • 57. Spring Boot Testing: Overview Spring Boot BOM(?) specifies following test-related dependencies: ● spring-boot-test ● spring-boot-test-autoconfigure ● spring-boot-starter-test ● solr-test-framework ● groovy-test ● groovy-testng ● hibernate-testing ● spring-batch-test ● spring-kafka-test ● spring-ldap-test ● spring-restdocs-webtestclient ● spring-ws-test
  • 58. Spring Boot Testing: Overview Spring Boot BOM(spring-boot-dependencies pom) specifies following test-related dependencies: ● spring-boot-test ● spring-boot-test-autoconfigure ● spring-boot-starter-test ● solr-test-framework ● groovy-test ● groovy-testng ● hibernate-testing ● spring-batch-test ● spring-kafka-test ● spring-ldap-test ● spring-restdocs-webtestclient ● spring-ws-test
  • 59. Spring Boot Testing: Overview We will mainly focus on these ones: ● spring-boot-test ● spring-boot-test-autoconfigure ● spring-boot-starter-test ● solr-test-framework ● groovy-test ● groovy-testng ● hibernate-testing ● spring-batch-test ● spring-kafka-test ● spring-ldap-test ● spring-restdocs-webtestclient ● spring-ws-test
  • 60. Spring Boot Testing: Overview Only one test-specific starter:
  • 61. Spring Test: Integration Testing Spring’s integration testing support has the following primary goals: ● To manage Spring IoC container caching between test execution. ● To provide Dependency Injection of test fixture instances. ● To provide transaction management appropriate to integration testing. ● To supply Spring-specific base classes that assist developers in writing integration tests.
  • 62. Spring Test: how are transactions handled? Your tests might run against a real database. It’s rare, but possible. We are talking about Integration tests after all. By default, the framework will create and roll back a transaction for each test. If a test method deletes the contents of selected tables while running within the transaction managed for the test, the transaction will rollback by default, and the database will return to its state prior to execution of the test.
  • 63. Spring Test: how are transactions handled? Your tests might run against a real database. It’s rare, but possible. We are talking about Integration tests after all. By default, the framework will create and roll back a transaction for each test. If a test method deletes the contents of selected tables while running within the transaction managed for the test, the transaction will rollback by default, and the database will return to its state prior to execution of the test. More flexibility is available via @Commit and @Rollback
  • 64. Spring Test: how are transactions handled? Your tests might run against a real database. It’s rare, but possible. We are talking about Integration tests after all. By default, the framework will create and roll back a transaction for each test. If a test method deletes the contents of selected tables while running within the transaction managed for the test, the transaction will rollback by default, and the database will return to its state prior to execution of the test. Not always that straightforward. Probably depends on implicit commits and DB engines. Will also only work for MOCK transport.
  • 65. Spring Test: main actors TestContextManager TestContext TestExecutionListeners
  • 66. Spring Test: TestContextManager Main entry point into Spring test related functionality Spring Test Context
  • 67. Spring Test: factories for ExecutionListener
  • 68. Spring Test: factories for ExecutionListener Will scan your test class, look at its annotations and add its logic accordingly.
  • 69. Spring Test: Reactive support The package org.springframework.mock.http.server.reactive contains mock implementations of ServerHttpRequest and ServerHttpResponse for use in WebFlux applications. The WebTestClient builds on the mock request and response to provide support for testing WebFlux applications without an HTTP server.
  • 70. Spring Test: static cache Test suites and forked processes The Spring TestContext framework stores application contexts in a static cache. This means that the context is literally stored in a static variable. In other words, if tests execute in separate processes the static cache will be cleared between each test execution, and this will effectively disable the caching mechanism.
  • 71. Spring Boot + Spock: pom file <plugin> <groupId>org.codehaus.gmavenplus</groupId> <artifactId>gmavenplus-plugin</artifactId> <configuration> <testSources> <testSource> <directory>${project.basedir}/src/test/java</directory> <includes> <include>**/*.groovy</include> </includes> </testSource> </testSources> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compileTests</goal> </goals> </execution> </executions> </plugin>
  • 72. Spring Boot + Spock: pom file <dependency> <groupId>org.spockframework</groupId> <artifactId>spock-core</artifactId> <version>1.1-groovy-2.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.spockframework</groupId> <artifactId>spock-spring</artifactId> <version>1.1-groovy-2.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.4.13</version> </dependency>
  • 73. Spring Boot + Spock: pom file <dependency> <groupId>org.spockframework</groupId> <artifactId>spock-core</artifactId> <version>1.1-groovy-2.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.spockframework</groupId> <artifactId>spock-spring</artifactId> <version>1.1-groovy-2.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.codehaus.groovy</groupId> <artifactId>groovy-all</artifactId> <version>2.4.13</version> </dependency> Default scope
  • 74. Spring Boot + Spock Integration with Spock: Detached mocks via the DetachedMockFactory and SpockMockFactoryBean classes. class TestConfigurationForSpock { private final detachedMockFactory = new DetachedMockFactory() @Bean BookingService bookingService() { detachedMockFactory.Mock(BookingService); } } Then just use: @Import(TestConfigurationForSpock)
  • 75. Spring Boot + JUnit 5 Will need to include an additional library to use JUnit 5 with Spring Framework 4.3
  • 76. Spring Boot + JUnit 5 There’s nothing at all Spock specific in spring-test, but you can find junit.jupiter is there:
  • 77. Spring Boot + JUnit 5 Be careful with your surefire version:
  • 78. Spring Boot + JUnit 5: pom file <dependency> <artifactId>junit-platform-launcher</artifactId> </dependency> <dependency> <artifactId>junit-jupiter-engine</artifactId> </dependency> <dependency> <artifactId>junit-vintage-engine</artifactId> </dependency> <dependency> <artifactId>junit-jupiter-api</artifactId> </dependency> <dependency> <artifactId>junit-jupiter-params</artifactId> </dependency> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.19.1</version> <configuration> <includes> <include>**/Test*.java</include> <include>**/*Test.java</include> <include>**/*Tests.java</include> <include>**/*TestCase.java</include> </includes> </configuration> <dependencies> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-surefire-provider</artifactId> <version>${junit.platform.version}</version> </dependency> </dependencies> </plugin>
  • 79. Spock vs JUnit 5: integration with Spring Both frameworks provide a class with exact same name: SpringExtension. However, the name is the only thing they have in common.
  • 80. Spock vs JUnit 5: integration with Spring SpringExtension Spock JUnit 5 Tries to find any Spring-specific annotation on a test class(spec): ContentHierarchy, BootstrapWith, ContextConfiguration. Using Spring-provided MetaAnnotaionUtils, so that it can traverse class hierarchy. Spring Test SpringExtention implements all possible JUnit 5 callbacks(.e.g.: BeforeAllCallback, AfterAllCallback) If found, creates a TestContextManager and delegate to it. Will either get TestContextManager from a store of create one. Attaches Spock-specific listener for managing Mocks: testContext.setAttribute(MOCKED_BEANS_LIST, mockedBeans); Will wrap TestContextManager calls and delegate to it. E.g.: public void beforeAll(ExtensionContext context) { getTestContextManager(context).beforeTestClass();
  • 81. Spring Boot: autoconfigure slicing Auto-configured tests The spring-boot-test-autoconfigure module includes a number of annotations that can be used to automatically configure different ‘slices’ of your app for testing purposes. Examples: ● @WebMvcTest ● @JsonTest ● @DataJpaTest ● @JdbcTest ● @DataMongoTest ● ...
  • 82. Spring Boot: autoconfigure slicing @*Test would normally contain several @AutoConfigure* annotations: For example: ... @BootstrapWith(SpringBootTestContextBootstrapper.class) @OverrideAutoConfiguration(enabled = false) @TypeExcludeFilters(DataJpaTypeExcludeFilter.class) @Transactional @AutoConfigureCache @AutoConfigureDataJpa @AutoConfigureTestDatabase @AutoConfigureTestEntityManager @ImportAutoConfiguration public @interface DataJpaTest
  • 83. Spring Boot: autoconfigure slicing To tweak @*Test mechanism, you can use a corresponding @AutoConfigure* annotation. For example: @RunWith(SpringRunner.class) @DataJpaTest @AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE) public class ExampleRepositoryTests { // ... }
  • 84. Spring Boot: autoconfigure slicing Have you noticed this relatively unremarkable meta annotation: @OverrideAutoConfiguration(enabled = false) It will effectively set: spring.boot.enableautoconfiguration=false via AbstractTestContextBootstrapper
  • 85. String Boot: Bootstrapping @BootstrapWith is used on @SpringBootTest, for example.
  • 86. String Boot: Bootstrapping @BootstrapWith is used on @SpringBootTest, for example. ● Aware of Spring Boot application structure; ● Helps SpringBootTest;
  • 87. String Boot: Bootstrapping As TestContextManager is the main entry point for test frameworks all they need is to create one: public TestContextManager(Class<?> testClass) { this(BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.createBootstrapContext(testClass))); }
  • 88. Spring Boot: Slicing Do not litter the application’s main class with configuration settings that are are specific to a particular area of its functionality. Extract them into specific @Configuration instead. Otherwise they will be picked up by all slice tests, which might not be what you want: @SpringBootApplication @EnableBatchProcessing - DO NOT DO IT THIS WAY public class SampleApplication { ... }
  • 89. Spring Boot: Custom component scanning Another source of confusion is classpath scanning. Assume that, while you structured your code in a sensible way, you need to scan an additional package. Your application may resemble the following code: @SpringBootApplication @ComponentScan({ "com.example.app", "org.acme.another" }) - ALSO BAD public class SampleApplication { ... } This effectively overrides the default component scan directive with the side effect of scanning those two packages regardless of the slice that you’ve chosen.
  • 90. Spring Boot: TypeExcludeFilter AutoConfigurationExcludeFilter - tells Spring Boot to exclude scanning autoconfigurations. To use SpringFactoriesLoader instead. TypeExcludeFilter - is an interesting case. While it’s in spring-boot jar, the doc actually says: primarily used internally to support spring-boot-test.
  • 91. Spring Boot: TypeExcludeFilter Pivotal cares about your application’s tests so much, they put a test-specific logic into their main Spring Boot module!
  • 92. Spring Boot: TypeExcludeFilter Indeed, all subclasses seem to be coming from spring-boot-test-autoconfigure and spring-boot-test:
  • 93. Spring Boot: TypeExcludeFilter What a specific test filter effectively does is: 1. Loads a corresponding annotation. E.g.: WebMvcTest for WebMvcTypeExcludeFilter, DataJpaTest for DataJpaTypeExcludeFilter; 2. Inside *ExcludeFilter add specific annotations for which you want to enable ComponentScan. For most *ExcludeFilters it is not required, however. They will simply rely on SpringFactoriesLoader
  • 94. @TestConfiguration : ● Unlike a nested @Configuration class which would be used instead of a your application’s primary configuration, a nested @TestConfiguration class will be used in addition to your application’s primary configuration; ● When placed on a top-level class, @TestConfiguration indicates that classes in src/test/java should not be picked up by scanning. Use explicit @Import to use them. Spring Boot: overriding configurations
  • 95. Spring Boot: Mocking and spying beans For example, you may have a facade over some remote service that’s unavailable during development. Spring Boot includes a @MockBean annotation that can be used to define a Mockito mock for a bean inside your ApplicationContext. @RunWith(SpringRunner.class) @SpringBootTest public class MyTests { @MockBean private RemoteService remoteService;
  • 96. Spring Boot: AutoConfigureMockMvc There is an option to not start the server at all, but test only the layer below that, where Spring handles the incoming HTTP request and hands it off to your controller. That way, almost the full stack is used, and your code will be called exactly the same way as if it was processing a real HTTP request, but without the cost of starting the server. To do that we will use Spring’s MockMvc, and we can ask for that to be injected for us by using the @AutoConfigureMockMvc annotation on the test case. https://spring.io/guides/gs/testing-web/
  • 97. Spring Boot: WebMvcTest @WebMvcTest Only web layer is instantiated, not the whole context. Often @WebMvcTest will be limited to a single controller and used in combination with @MockBean to provide mock implementations for required collaborators.
  • 98. Spring Boot: WebMvcTest vs AutoConfigureMockMvc vs SpringBootTest The main difference is inside META-INF/spring.factories: # AutoConfigureMockMvc auto-configuration imports org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc= org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration You’ll notice that WebMvcTest has also a @ImportAutoConfiguration *, but there’s no entry in spring.factories for it. https://spring.io/blog/2016/08/30/custom-test-slice-with-spring-boot-1-4
  • 99. Spring Boot: WebMvcTest vs AutoConfigureMockMvc vs SpringBootTest The main difference is inside META-INF/spring.factories: # AutoConfigureMockMvc auto-configuration imports org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc= org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration You’ll notice that WebMvcTest has also a @ImportAutoConfiguration *, but there’s no entry in spring.factories for it. However it has an exclude filter to reduce the amount of scanned objects.
  • 100. Spring Boot: SpringBootTest MOCK WebEnvironment Embedded servlet containers are not started when using this attribute. Can be used in conjunction with @AutoConfigureMockMvc for MockMvc-based testing of your application.
  • 101. Spring Boot: SpringBootTest RANDOM_PORT/DEFINED_PORT WebEnvironment A test like this will run perfectly fine with real HTTP transport: @SpringBootTest(classes = RamlBasedProducerApplication, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc @OverrideAutoConfiguration(enabled = true) class BookingServiceImplSpockTest extends Specification { @LocalServerPort private int port; @Autowired MockMvc mockMvc; Spring will inject different ServletContexts into MockMvc depending on webEnv.
  • 102. Spring Boot: Test utilities ● EnvironmentTestUtils(addEnvironment(env, "org=Spring", "name=Boot")) ● TestRestTemplate(behave in a test-friendly way by not throwing exceptions on server-side errors) ● MockRestServiceServer(part of Spring Test)

Editor's Notes

  • #25: Mention Spring Boot logo and “whatever”
  • #27: https://gist.github.com/jeffsheets/ada3de8fe4a536e5351b
  • #28: Can also be a multi-variable data pipe(a list from the left hand side)
  • #29: Can also be a multi-variable data pipe(a list from the left hand side)
  • #30: @Unroll - another cool feature.
  • #31: https://gist.github.com/jeffsheets/ada3de8fe4a536e5351b
  • #33: http://jakubdziworski.github.io/java/groovy/spock/2016/05/14/spock-cheatsheet.html
  • #42: Spock - no official logo. WTF?
  • #47: If they say it’s a ball of mud, it’s probably so.
  • #48: https://www.youtube.com/watch?v=oGaatK5ShUs
  • #50: http://mvpjava.com/spring-boot-junit5/ https://www.youtube.com/watch?time_continue=9&v=K60vyIHAUOQ
  • #63: If you want a transaction to commit — unusual, but occasionally useful when you want a particular test to populate or modify the database — the TestContext framework can be instructed to cause the transaction to commit instead of roll back via the@Commit annotation.
  • #64: If you want a transaction to commit — unusual, but occasionally useful when you want a particular test to populate or modify the database — the TestContext framework can be instructed to cause the transaction to commit instead of roll back via the@Commit annotation.
  • #65: If you want a transaction to commit — unusual, but occasionally useful when you want a particular test to populate or modify the database — the TestContext framework can be instructed to cause the transaction to commit instead of roll back via the@Commit annotation.
  • #66: If you want a transaction to commit — unusual, but occasionally useful when you want a particular test to populate or modify the database — the TestContext framework can be instructed to cause the transaction to commit instead of roll back via the@Commit annotation.
  • #67: If you want a transaction to commit — unusual, but occasionally useful when you want a particular test to populate or modify the database — the TestContext framework can be instructed to cause the transaction to commit instead of roll back via the@Commit annotation.
  • #68: Talk about TestContextmanager and TestContext
  • #69: Talk about TestContextmanager and TestContext
  • #79: All test scope
  • #80: public TestContextManager(Class<?> testClass) { this(BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.createBootstrapContext(testClass))); }
  • #81: public TestContextManager(Class<?> testClass) { this(BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.createBootstrapContext(testClass))); }
  • #82: Several at once can cauae problems.
  • #97: https://spring.io/guides/gs/testing-web/
  • #99: https://spring.io/blog/2016/08/30/custom-test-slice-with-spring-boot-1-4
  • #100: https://spring.io/blog/2016/08/30/custom-test-slice-with-spring-boot-1-4