SlideShare une entreprise Scribd logo
1  sur  84
Testing Spring Boot application in post-JUnit
4 world
About myself
● Application Architect
@Thomas Cook/Ciklum
● Tech Lead - Platformers
team
● +9 years Java
Agenda
1. What problems we are facing with legacy testing frameworks;
2. Alternative frameworks - Spock and JUnit 5;
3. Spring Boot testing support under the hood;
4. Demo
Mule -> Spring Boot
Mule -> Spring Boot
TestNG + JUnit 4
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;
Issues with JUnit 4
Not possible to have several @RunWith(imagine you want
MockitoJUnitRunner and SpringRunner)
What are the alternatives?
Spock: Overview
Modules
● spock-core
● spock-specs
● spock-spring
● spock-tapestry
● spock-guice
● …..
Spock: based on JUnit runner
No hassle with the runner: it even 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
● setup:
● when:
● then:
● expect:
● cleanup:
● where:
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 and Tables
where:
a | b || c
3 | 5 || 5
7 | 0 || 7
where:
a << [3, 7, 0]
b << [5, 0, 0]
c << [5, 7, 0]
Spock: @Shared fields
For expensive resources:
@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)
Spock: Interactions
A way to express which method invocations are expected to occur:
(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 but should be
used at your own risk
1 * subscriber./r.*e/("hello") //method name starts with 'r' and ends in 'e')
1 * subscriber.receive(_) // any single argument (including null)
1 * subscriber.receive(*_) // any argument list (incl. 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
Spock Drawbacks: new language
If you start writing tests for more than just basic CRUD APIs, you’ll
have to learn it.
Groovy: with great power...
Groovy “gems”
Everything associated with dynamic typing/duck typing should be treated
with extra care:
https://stackoverflow.com/questions/9072307/copy-groovy-class-properties/9072974#9072974
Groovy “gems”
https://stackoverflow.com/questions/46952475/copy-object-properties-to-another-object-in-groovy
Groovy “gems”
Comments/Answers:
JUnit 5: finally released!
JUnit 5: motivation
JUnit 5: module composition
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: reason for re-architecture
● JUnit 4 test discovery and execution were tightly coupled.
● JUnit 4 - java 5 compatible - that’s ridiculous!
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()));
}
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
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: Missing fixed method execution order
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 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 Boot Testing: Overview
Only one test-specific starter:
Spring Test: Integration Testing
Spring 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?
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?
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?
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
org.springframework.test.context.TestExecutionListener = 
org.springframework.test.context.web.ServletTestExecutionListener,
org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener,
org.springframework.test.context.support.DependencyInjectionTestExecutionListener,
org.springframework.test.context.support.DirtiesContextTestExecutionListener,
org.springframework.test.context.transaction.TransactionalTestExecutionListener,
org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener
Spring Test: factories for ExecutionListener
Will scan your test class, look at its annotations and add its logic
accordingly.
org.springframework.test.context.TestExecutionListener = 
org.springframework.test.context.web.ServletTestExecutionListener,
org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener,
org.springframework.test.context.support.DependencyInjectionTestExecutionListener,
org.springframework.test.context.support.DirtiesContextTestExecutionListener,
org.springframework.test.context.transaction.TransactionalTestExecutionListener,
org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener
Spring Test: static cache
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
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 + Spock: Compilation/Build
caveat
GMavenPlus plugin is far from being perfect.
Check https://github.com/groovy/GMavenPlus/issues/ for issues reports.
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: Compilation/Build
caveat
Not a single jar any more. If you can’t migrate all tests at once you will
need to have both junit 4 and junit 5 on your test classpath.
Spock vs JUnit 5: integration with Spring
Both frameworks provide a class with exact same name:
SpringExtension.
However, their 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
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
By applying ContextCustomizer to ContextLoader
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(TestContextBootstrapper testContextBootstrapper) {
this.testContext = testContextBootstrapper.buildTestContext();
registerTestExecutionListeners(testContextBootstrapper.getTestExecutionList
eners());
}
Spring Boot: Slicing
Do not litter the application’s main class with configuration settings that
are specific to a particular area of its functionality.
Extract them into specific @Configuration instead.
@SpringBootApplication
@EnableBatchProcessing - DO NOT DO IT THIS WAY
public class SampleApplication { ... }
Spring Boot: Custom component scanning
If 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.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
Spring Boot: TypeExcludeFilter
Pivotal guys care about your application’s tests so much, they put a
test-specific logic into their main Spring Boot module!
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
Spring Boot: TypeExcludeFilter
Indeed, all subclasses seem to be coming from spring-boot-test-
autoconfigure and spring-boot-test:
@TestConfiguration :
● Unlike a nested @Configuration class which would be used instead of
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
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
Enables you to use MockMvc for any WebEnvironment(MOCK,
RANDOM_PORT, etc.)
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: @ImportAutoConfiguration
@EnableAutoConfiguration - will scan spring.factories for itself.
@ImportAutoConfiguration - will scan spring.factories for the annotated
class entry.
Spring Boot: WebMvcTest vs
AutoConfigureMockMvc
You’ll notice that both WebMvcTest and AutoConfigureMockMvc have a
@ImportAutoConfiguration, but there’s no entry in spring.factories for
WebMvcTest. By design it allows for extensibility. You can add your
own WebMvcTest entry.
In general, WebMvcTest has a lot more configurations but also contains
exclude filter to narrow down it’s search to only web-related components.
Spring Test: Reactive support
The WebTestClient builds on the mock request and response to provide
support for testing WebFlux applications without an HTTP server.
Testing reactive apps: same concepts with
different names
Non-reactive Reactive
@SpringBootTest @SpringBootTest
@WebMvcTest @WebFluxTest
@AutoConfigureMockMvc @AutoConfigureWebTestClient
One important limitation
If you want to understand your reactive code
inside out:
@Test
public void testSteppingThroughFlux() {
Flux<Long> flux = Flux.just(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L);
StepVerifier.create(flux)
.expectNext(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L)
.expectComplete()
.verify();
Spring Boot: SpringBootTest
RANDOM_PORT WebEnvironment
@SpringBootTest(classes = RamlBasedProducerApplication, webEnvironment =
SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class BookingServiceImplSpockTest extends Specification {
@LocalServerPort
private int port;
@Autowired
MockMvc mockMvc;
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)
Demo
Let’s take a look at a set of CRUD tests and re-write them
using JUnit 5, Spock and different Spring Boot/Spring
Framework test features.
https://github.com/yuranos/raml-based-producer-application
https://github.com/yuranos/raml-based-consumer-application
(unit_testing branch)
Thank you!
Mail: yura.v.nosenko@gmail.com
Linkedin: https://www.linkedin.com/in/yuranos/

Contenu connexe

Tendances

L'API Collector dans tous ses états
L'API Collector dans tous ses étatsL'API Collector dans tous ses états
L'API Collector dans tous ses étatsJosé Paumard
 
softCours design pattern m youssfi partie 9 creation des objets abstract fact...
softCours design pattern m youssfi partie 9 creation des objets abstract fact...softCours design pattern m youssfi partie 9 creation des objets abstract fact...
softCours design pattern m youssfi partie 9 creation des objets abstract fact...ENSET, Université Hassan II Casablanca
 
Les dessous du framework spring
Les dessous du framework springLes dessous du framework spring
Les dessous du framework springAntoine Rey
 
Alphorm.com Formation Big Data avec Apache Spark: Initiation
Alphorm.com Formation Big Data avec Apache Spark: InitiationAlphorm.com Formation Big Data avec Apache Spark: Initiation
Alphorm.com Formation Big Data avec Apache Spark: InitiationAlphorm
 
Java 8 - collections et stream
Java 8 - collections et streamJava 8 - collections et stream
Java 8 - collections et streamFranck SIMON
 
Appalications JEE avec Servlet/JSP
Appalications JEE avec Servlet/JSPAppalications JEE avec Servlet/JSP
Appalications JEE avec Servlet/JSPYouness Boukouchi
 
Cours JavaScript.ppt
Cours JavaScript.pptCours JavaScript.ppt
Cours JavaScript.pptPROFPROF11
 
Fascicule de tp atelier développement web
Fascicule de tp atelier développement webFascicule de tp atelier développement web
Fascicule de tp atelier développement webHouda TOUKABRI
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications JavaAntoine Rey
 
Intégration continue et déploiement continue avec Jenkins
Intégration continue et déploiement continue avec JenkinsIntégration continue et déploiement continue avec Jenkins
Intégration continue et déploiement continue avec JenkinsKokou Gaglo
 
JDBC: Gestion des bases de données en Java
JDBC: Gestion des bases de données en Java JDBC: Gestion des bases de données en Java
JDBC: Gestion des bases de données en Java Youness Boukouchi
 

Tendances (20)

L'API Collector dans tous ses états
L'API Collector dans tous ses étatsL'API Collector dans tous ses états
L'API Collector dans tous ses états
 
softCours design pattern m youssfi partie 9 creation des objets abstract fact...
softCours design pattern m youssfi partie 9 creation des objets abstract fact...softCours design pattern m youssfi partie 9 creation des objets abstract fact...
softCours design pattern m youssfi partie 9 creation des objets abstract fact...
 
Support distributed computing and caching avec hazelcast
Support distributed computing and caching avec hazelcastSupport distributed computing and caching avec hazelcast
Support distributed computing and caching avec hazelcast
 
Les dessous du framework spring
Les dessous du framework springLes dessous du framework spring
Les dessous du framework spring
 
Alphorm.com Formation Big Data avec Apache Spark: Initiation
Alphorm.com Formation Big Data avec Apache Spark: InitiationAlphorm.com Formation Big Data avec Apache Spark: Initiation
Alphorm.com Formation Big Data avec Apache Spark: Initiation
 
Python avancé : Classe et objet
Python avancé : Classe et objetPython avancé : Classe et objet
Python avancé : Classe et objet
 
Java 8 - collections et stream
Java 8 - collections et streamJava 8 - collections et stream
Java 8 - collections et stream
 
Appalications JEE avec Servlet/JSP
Appalications JEE avec Servlet/JSPAppalications JEE avec Servlet/JSP
Appalications JEE avec Servlet/JSP
 
Cours JavaScript.ppt
Cours JavaScript.pptCours JavaScript.ppt
Cours JavaScript.ppt
 
Cours design pattern m youssfi partie 4 composite
Cours design pattern m youssfi partie 4 compositeCours design pattern m youssfi partie 4 composite
Cours design pattern m youssfi partie 4 composite
 
Python avancé : Lecture et écriture de fichiers
Python avancé : Lecture et écriture de fichiersPython avancé : Lecture et écriture de fichiers
Python avancé : Lecture et écriture de fichiers
 
Les Servlets et JSP
Les Servlets et JSPLes Servlets et JSP
Les Servlets et JSP
 
Fascicule de tp atelier développement web
Fascicule de tp atelier développement webFascicule de tp atelier développement web
Fascicule de tp atelier développement web
 
Java EE _ JSTL (1).pdf
Java EE _ JSTL (1).pdfJava EE _ JSTL (1).pdf
Java EE _ JSTL (1).pdf
 
Support JEE Spring Inversion de Controle IOC et Spring MVC
Support JEE Spring Inversion de Controle IOC et Spring MVCSupport JEE Spring Inversion de Controle IOC et Spring MVC
Support JEE Spring Inversion de Controle IOC et Spring MVC
 
JAVA
JAVAJAVA
JAVA
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications Java
 
Hibernate jpa
Hibernate jpaHibernate jpa
Hibernate jpa
 
Intégration continue et déploiement continue avec Jenkins
Intégration continue et déploiement continue avec JenkinsIntégration continue et déploiement continue avec Jenkins
Intégration continue et déploiement continue avec Jenkins
 
JDBC: Gestion des bases de données en Java
JDBC: Gestion des bases de données en Java JDBC: Gestion des bases de données en Java
JDBC: Gestion des bases de données en Java
 

Similaire à Testing Spring Boot application in post-JUnit 4 world

Whitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsWhitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsYura Nosenko
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMockYing Zhang
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and ProsperKen Kousen
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock FrameworkEugene Dvorkin
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentAll Things Open
 
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 VersionSchalk Cronjé
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testingpleeps
 
Ive posted 3 classes after the instruction that were given at star.pdf
Ive posted 3 classes after the instruction that were given at star.pdfIve posted 3 classes after the instruction that were given at star.pdf
Ive posted 3 classes after the instruction that were given at star.pdfdeepaarora22
 
Ruby for C# Developers
Ruby for C# DevelopersRuby for C# Developers
Ruby for C# DevelopersCory Foy
 
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 TestSchalk Cronjé
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everythingnoelrap
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingVisual Engineering
 
2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good Tests2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good TestsTomek Kaczanowski
 
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Andrzej Jóźwiak
 

Similaire à Testing Spring Boot application in post-JUnit 4 world (20)

Whitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsWhitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applications
 
Mockito with a hint of PowerMock
Mockito with a hint of PowerMockMockito with a hint of PowerMock
Mockito with a hint of PowerMock
 
Spock
SpockSpock
Spock
 
Spock
SpockSpock
Spock
 
Spock: Test Well and Prosper
Spock: Test Well and ProsperSpock: Test Well and Prosper
Spock: Test Well and Prosper
 
Unit testing with Spock Framework
Unit testing with Spock FrameworkUnit testing with Spock Framework
Unit testing with Spock Framework
 
Junit_.pptx
Junit_.pptxJunit_.pptx
Junit_.pptx
 
We Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End DevelopmentWe Are All Testers Now: The Testing Pyramid and Front-End Development
We Are All Testers Now: The Testing Pyramid and Front-End Development
 
Spock Framework
Spock FrameworkSpock Framework
Spock Framework
 
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
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Ive posted 3 classes after the instruction that were given at star.pdf
Ive posted 3 classes after the instruction that were given at star.pdfIve posted 3 classes after the instruction that were given at star.pdf
Ive posted 3 classes after the instruction that were given at star.pdf
 
Ruby for C# Developers
Ruby for C# DevelopersRuby for C# Developers
Ruby for C# Developers
 
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
 
How To Test Everything
How To Test EverythingHow To Test Everything
How To Test Everything
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
 
2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good Tests2013 DevFest Vienna - Bad Tests, Good Tests
2013 DevFest Vienna - Bad Tests, Good Tests
 
Unit testing - A&BP CC
Unit testing - A&BP CCUnit testing - A&BP CC
Unit testing - A&BP CC
 
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
Do I need tests when I have the compiler - Andrzej Jóźwiak - TomTom Dev Day 2020
 
Java For Automation
Java   For AutomationJava   For Automation
Java For Automation
 

Dernier

The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is insideshinachiaurasa2
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...masabamasaba
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024VictoriaMetrics
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension AidPhilip Schwarz
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in sowetomasabamasaba
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile EnvironmentVictorSzoltysek
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Bert Jan Schrijver
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...masabamasaba
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...masabamasaba
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2
 
tonesoftg
tonesoftgtonesoftg
tonesoftglanshi9
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 

Dernier (20)

The title is not connected to what is inside
The title is not connected to what is insideThe title is not connected to what is inside
The title is not connected to what is inside
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT  - Elevating Productivity in Today's Agile EnvironmentHarnessing ChatGPT  - Elevating Productivity in Today's Agile Environment
Harnessing ChatGPT - Elevating Productivity in Today's Agile Environment
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
Devoxx UK 2024 - Going serverless with Quarkus, GraalVM native images and AWS...
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Atlanta Psychic Readings, Attraction spells,Brin...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 

Testing Spring Boot application in post-JUnit 4 world

  • 1. Testing Spring Boot application in post-JUnit 4 world
  • 2. About myself ● Application Architect @Thomas Cook/Ciklum ● Tech Lead - Platformers team ● +9 years Java
  • 3. Agenda 1. What problems we are facing with legacy testing frameworks; 2. Alternative frameworks - Spock and JUnit 5; 3. Spring Boot testing support under the hood; 4. Demo
  • 5. Mule -> Spring Boot TestNG + JUnit 4
  • 6. TestNG issues Test class lifecycle: @BeforeMethod private void beforeMethod() { objectUnderTest = null; MockitoAnnotations.initMocks(this); …. }
  • 7. 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;
  • 8. Issues with JUnit 4 Not possible to have several @RunWith(imagine you want MockitoJUnitRunner and SpringRunner)
  • 9. What are the alternatives?
  • 10. Spock: Overview Modules ● spock-core ● spock-specs ● spock-spring ● spock-tapestry ● spock-guice ● …..
  • 11. Spock: based on JUnit runner No hassle with the runner: it even 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
  • 12. Spock: formal semantics JUnit tests lack formal semantics The number one reason for using Spock is to make your tests more readable.
  • 13. Spock: test blocks ● setup: ● when: ● then: ● expect: ● cleanup: ● where:
  • 14. 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" }
  • 15. Spock: Data Pipes and Tables where: a | b || c 3 | 5 || 5 7 | 0 || 7 where: a << [3, 7, 0] b << [5, 0, 0] c << [5, 7, 0]
  • 16. Spock: @Shared fields For expensive resources: @Shared res = new VeryExpensiveResource()
  • 17. Spock: error reporting Nice and layered: Condition not satisfied: content.passengerName == result | | | | | Bob | Bob1 | false | 1 difference (75% similarity) | Bob(-) | Bob(1)
  • 18. Spock: Interactions A way to express which method invocations are expected to occur: (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
  • 19. Spock: Interactions - powerful but should be used at your own risk 1 * subscriber./r.*e/("hello") //method name starts with 'r' and ends in 'e') 1 * subscriber.receive(_) // any single argument (including null) 1 * subscriber.receive(*_) // any argument list (incl. the empty argument list) 1 * _._ // any method call on any mock object 1 * _ // shortcut for and preferred over the above
  • 20. Spock Drawbacks: A bit scary versioning
  • 21. Spock Drawbacks: new language If you start writing tests for more than just basic CRUD APIs, you’ll have to learn it.
  • 22. Groovy: with great power...
  • 23. Groovy “gems” Everything associated with dynamic typing/duck typing should be treated with extra care: https://stackoverflow.com/questions/9072307/copy-groovy-class-properties/9072974#9072974
  • 26. JUnit 5: finally released!
  • 28. JUnit 5: module composition JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage
  • 29. 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.
  • 30. JUnit 5: reason for re-architecture ● JUnit 4 test discovery and execution were tightly coupled. ● JUnit 4 - java 5 compatible - that’s ridiculous!
  • 31. JUnit 5: powerful @ExtendWith Only one @RunWith but many @ExtendWith: @ExtendWith(SpringExtension.class)
  • 32. 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())); }
  • 33. 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 Fail Fail Pass
  • 34. JUnit 5: asserts are never skipped Will require fewer iterations to stabilize your code
  • 35. 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);
  • 36. 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();
  • 37. 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.
  • 38. JUnit 5: Missing fixed method execution order
  • 39. 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 ● ...
  • 40. 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 ● ...
  • 41. Spring Boot Testing: Overview Only one test-specific starter:
  • 42. Spring Test: Integration Testing Spring 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.
  • 43. Spring Test: how are transactions handled? 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.
  • 44. Spring Test: how are transactions handled? 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
  • 45. Spring Test: how are transactions handled? 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.
  • 46. Spring Test: main actors TestContextManager TestContext TestExecutionListeners
  • 47. Spring Test: TestContextManager Main entry point into Spring test related functionality Spring Test Context
  • 48. Spring Test: factories for ExecutionListener org.springframework.test.context.TestExecutionListener = org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener
  • 49. Spring Test: factories for ExecutionListener Will scan your test class, look at its annotations and add its logic accordingly. org.springframework.test.context.TestExecutionListener = org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener
  • 50. Spring Test: static cache 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.
  • 51. Spring Boot + 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)
  • 52. Spring Boot + Spock: Compilation/Build caveat GMavenPlus plugin is far from being perfect. Check https://github.com/groovy/GMavenPlus/issues/ for issues reports.
  • 53. Spring Boot + JUnit 5 Will need to include an additional library to use JUnit 5 with Spring Framework 4.3
  • 54. Spring Boot + JUnit 5 There’s nothing at all Spock specific in spring-test, but you can find junit.jupiter is there:
  • 55. Spring Boot + JUnit 5 Be careful with your surefire version:
  • 56. Spring Boot + JUnit 5: Compilation/Build caveat Not a single jar any more. If you can’t migrate all tests at once you will need to have both junit 4 and junit 5 on your test classpath.
  • 57. Spock vs JUnit 5: integration with Spring Both frameworks provide a class with exact same name: SpringExtension. However, their name is the only thing they have in common.
  • 58. 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();
  • 59. Spring Boot: autoconfigure slicing 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 ● ...
  • 60. 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
  • 61. 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 { // ... }
  • 62. Spring Boot: autoconfigure slicing Have you noticed this relatively unremarkable meta annotation: @OverrideAutoConfiguration(enabled = false) It will effectively set: spring.boot.enableautoconfiguration=false By applying ContextCustomizer to ContextLoader
  • 63. String Boot: Bootstrapping @BootstrapWith is used on @SpringBootTest, for example.
  • 64. String Boot: Bootstrapping @BootstrapWith is used on @SpringBootTest, for example. ● Aware of Spring Boot application structure; ● Helps SpringBootTest;
  • 65. String Boot: Bootstrapping As TestContextManager is the main entry point for test frameworks; all they need is to create one: public TestContextManager(TestContextBootstrapper testContextBootstrapper) { this.testContext = testContextBootstrapper.buildTestContext(); registerTestExecutionListeners(testContextBootstrapper.getTestExecutionList eners()); }
  • 66. Spring Boot: Slicing Do not litter the application’s main class with configuration settings that are specific to a particular area of its functionality. Extract them into specific @Configuration instead. @SpringBootApplication @EnableBatchProcessing - DO NOT DO IT THIS WAY public class SampleApplication { ... }
  • 67. Spring Boot: Custom component scanning If 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.
  • 68. 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. @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
  • 69. Spring Boot: TypeExcludeFilter Pivotal guys care about your application’s tests so much, they put a test-specific logic into their main Spring Boot module! @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
  • 70. Spring Boot: TypeExcludeFilter Indeed, all subclasses seem to be coming from spring-boot-test- autoconfigure and spring-boot-test:
  • 71. @TestConfiguration : ● Unlike a nested @Configuration class which would be used instead of 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
  • 72. Spring Boot: Mocking and spying beans 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;
  • 73. Spring Boot: AutoConfigureMockMvc Enables you to use MockMvc for any WebEnvironment(MOCK, RANDOM_PORT, etc.)
  • 74. 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.
  • 75. Spring Boot: @ImportAutoConfiguration @EnableAutoConfiguration - will scan spring.factories for itself. @ImportAutoConfiguration - will scan spring.factories for the annotated class entry.
  • 76. Spring Boot: WebMvcTest vs AutoConfigureMockMvc You’ll notice that both WebMvcTest and AutoConfigureMockMvc have a @ImportAutoConfiguration, but there’s no entry in spring.factories for WebMvcTest. By design it allows for extensibility. You can add your own WebMvcTest entry. In general, WebMvcTest has a lot more configurations but also contains exclude filter to narrow down it’s search to only web-related components.
  • 77. Spring Test: Reactive support The WebTestClient builds on the mock request and response to provide support for testing WebFlux applications without an HTTP server.
  • 78. Testing reactive apps: same concepts with different names Non-reactive Reactive @SpringBootTest @SpringBootTest @WebMvcTest @WebFluxTest @AutoConfigureMockMvc @AutoConfigureWebTestClient
  • 80. If you want to understand your reactive code inside out: @Test public void testSteppingThroughFlux() { Flux<Long> flux = Flux.just(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L); StepVerifier.create(flux) .expectNext(0L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L) .expectComplete() .verify();
  • 81. Spring Boot: SpringBootTest RANDOM_PORT WebEnvironment @SpringBootTest(classes = RamlBasedProducerApplication, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc class BookingServiceImplSpockTest extends Specification { @LocalServerPort private int port; @Autowired MockMvc mockMvc;
  • 82. 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)
  • 83. Demo Let’s take a look at a set of CRUD tests and re-write them using JUnit 5, Spock and different Spring Boot/Spring Framework test features. https://github.com/yuranos/raml-based-producer-application https://github.com/yuranos/raml-based-consumer-application (unit_testing branch)
  • 84. Thank you! Mail: yura.v.nosenko@gmail.com Linkedin: https://www.linkedin.com/in/yuranos/

Notes de l'éditeur

  1. There are a lot of presentations about JUnit, for example, but it doesn’t bring most people closer to a real adoption. This presentation is to explain the effort and the risks in migration to a newer testing framework.
  2. When Spring Test docs say “use with JUnit runner”, you actually don’t need it when you use Spock.
  3. Mention Spring Boot logo and “whatever”
  4. https://gist.github.com/jeffsheets/ada3de8fe4a536e5351b
  5. Can also be a multi-variable data pipe(a list from the left hand side)
  6. @Unroll - another cool feature.
  7. https://gist.github.com/jeffsheets/ada3de8fe4a536e5351b
  8. http://jakubdziworski.github.io/java/groovy/spock/2016/05/14/spock-cheatsheet.html
  9. 0 * _ Interesting and very useful case - 0 cardinality.
  10. Spock - no official logo. WTF?
  11. If they say it’s a ball of mud, it’s probably so.
  12. http://mvpjava.com/spring-boot-junit5/ https://www.youtube.com/watch?time_continue=9&v=K60vyIHAUOQ
  13. For example, you might need ObjectMapper for some tests, but not for others.
  14. https://github.com/junit-team/junit5/issues/13
  15. Your tests might run against a real database. It’s rare, but possible. We are talking about Integration tests after all. 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. merge() will only care about an auto-generated id(tested on IDENTITY and SEQUENCE) when a record with such an id already exists in your table. In that case merge() will try to update the record. If, however, an id is absent or is not matching any existing records, merge() will completely ignore it and ask a db to allocate a new one. This is sometimes a source of a lot of bugs. Do not use merge() to force an id for a new record.
  16. Talk about TestContextmanager and TestContext
  17. Talk about TestContextmanager and TestContext
  18. Test suites and forked processes
  19. All test scope
  20. public TestContextManager(Class<?> testClass) { this(BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.createBootstrapContext(testClass))); }
  21. public TestContextManager(Class<?> testClass) { this(BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.createBootstrapContext(testClass))); }
  22. Several at once can cause problems.
  23. Everything that starts with @AutoConfigure… is good for fine-tuning.
  24. Can’t use 2 annotations that rely on 2 different @Bootstraps under the hood.
  25. Otherwise they will be picked up by all slice tests, which might not be what you want:
  26. 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.
  27. protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return false; } } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false; } In ClassPathScanningCandidateComponentProvider
  28. protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return false; } } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false; } In ClassPathScanningCandidateComponentProvider
  29. private boolean containsNonTestComponent(Class<?>[] classes) { for (Class<?> candidate : classes) { if (!AnnotatedElementUtils.isAnnotated(candidate, TestConfiguration.class)) { return true; } } return false; } In SpringBootTestContextBootstrapper
  30. For example, you may have a facade over some remote service that’s unavailable during development.
  31. 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/
  32. This allows for more granular configuration.
  33. https://spring.io/blog/2016/08/30/custom-test-slice-with-spring-boot-1-4
  34. The package org.springframework.mock.http.server.reactive contains mock implementations of ServerHttpRequest and ServerHttpResponse for use in WebFlux applications.
  35. So, @SpringBootTest works fine, but @WebFluxTest - doesn’t. Apart from that there are a lot of problems with JUnit 5. A lot of options to configure WebTestClient. Maybe the issues where Undertow specific.
  36. If you want to go beyond Spring’s native support, and dig deeper into Flux and Mono - go for reactor-test. https://www.programcreek.com/java-api-examples/?api=reactor.test.StepVerifier