SlideShare a Scribd company logo
1 of 71
Testing Spring
Applications
Riyadh Java Meetup
Mohammad Hewedy
github.com/mhewedy
1
1
Agenda
● Unit Test: What and Why?
● Test Driven Development
● Test Patterns
● Test Doubles
● Testing Spring Applications
○ Unit Testing
○ Integration Testing and the TestContext Framework
○ Slice Testing in Spring boot
● Demo
2
What?
3
4
A unit test is a piece of code written by a developer that exercises a very small,
specific area of functionality of the code being tested.
Unit tests are performed to prove that a piece of code does what the
developer thinks it should do.
Pragmatic Unit Testing in Java with JUnit
5
Why?
6
● It will make your designs better.
● Reduce the amount of time you spend debugging.
● Give confidence in the code.
● Make sure code do what you want.
● Do what you want all of the Time.
● Make sure you can depend on code.
● Document your intent.
● Shows how to use your code.
● Avoid any collateral damage
7
“Whac-a-Mole” effect
https://www.bakadesuyo.com/2012/10/whac-a-mole-teach-ability-focus/
8
a.k.a. “Samir Ghanem” effect
9
Why not?
10
● It takes too much time to write the tests?
● It takes too long to run the tests?
● It’s not my job to test my code?
● I’m being paid to write code, not to write tests?
● I feel guilty about putting testers and QA staff out of work?
11
Test Pyramid
Unit Tests
Integration Tests
(Service Tests)
E2E Tests
(UI Tests)
Fast
Slow
12
Characteristics of Good Tests
● Automatic
● Thorough
● Repeatable
● Independent
● Professional
● Speed
13
Always, “Spring The Trap”
Jim Baird - Adventurer
14
How?
15
class MathTest(TestCase):
def test_add(self):
math = Math()
result = math.add(10, 20)
assert_equals(30, result)
def test_multiply(self):
math = Math()
result = math.multiply(10, 20)
assert_equals(200, result)
class Math:
def add(self, x, y):
return x + y
def multiply(self, x, y):
return x * y
16
Test Driven Development
Red/Green/Refactor
Write
a test
Make it
compile
Run to
see it
fails
Make it
run
(see next)
Remove
Duplicate
(Refactor)
17
How to “Make it run” (Geen Bar Pattern)
1. Fake it
2. Triangulate
3. Obvious implementation
18
Green Bar Pattern in Action
19
Test Patterns
● Arrange, Act, Assert.
● Arrange, Assert-not, Act, Assert.
● Given, When, Then.
● Setup, Exercise, Verify, Teardown.
20
// spock framework
def "test listToString"() {
given:
def list = Arrays.asList("HELLO", "WORLD")
when:
def listToString = Util.listToString(list)
then:
listToString == "HELLOnWORLDn"
}
https://github.com/mhewedy/spwrap/blob/master/src/test/groovy/spwrap/UtilTest.groovy
21
@Unroll
def "#testDB : using implicit ResultSet Mapper to map result set"() {
given:
setup(testDB)
when:
customerDao.createCustomer0(“Abdullah”, “Mohammad”)
def list = customerDao.listCustomers(list)
then:
1 == list.size()
with(list.get(0)){
“Abdullah” == firstName()
“Mohammad” == lastName()
}
cleanup:
cleanup(testDB)
where:
testDB << [HSQL, MYSQL, SQLServer, ORACLE]
}
22
https://github.com/mhewedy/spwrap/blob/master/src/test/groovy/spwrap/DAOIntTest.groovy
Test Doubles
23
interface Mailer {
Boolean send(String to, String subject);
}
// billing is SUT
billing.bill(cusomer);
// mailer is collaborator
mailer.send(cusomer.getEmail(), postBillHtmlTemplate);
Collaborator object vs SUT
24
Dummy
class DummyMailer implements Mailer {
Boolean send(String to, String subject) {
return null;
}
}
25
Stub
class SuccessfullySendingMailerStub implements Mailer {
Boolean send(String to, String subject) {
return true;
}
}
26
Spy
class SuccessfullySendingMailerSpy implements Mailer {
public int callCount;
public String recordedTo;
public String recordedSubject;
Boolean send(String to, String subject) {
this.callCount += 1;
this.recordedTo = to;
this.recordedSubject = subject;
return true;
}
}
27
Mock
class SuccessfullySendingMailerMock implements Mailer {
private int callCount;
private String recordedTo;
private String recordedSubject;
Boolean send(String to, String subject) {
this.callCount += 1;
this.recordedTo = to;
this.recordedSubject = subject;
return true;
}
boolean verify(String expectedTo, String expectedSubject) {
return callCount == 1 &&
this.recordedTo.equals(expectedTo) &&
this.recordedSubject.equals(expectedSubject);
}
} 28
Fake
class MailerFake implements Mailer {
Boolean send(String to, String subject) {
return SimulatorDataSource.getMailer()
.containsRecord(to, subject);
}
}
29
To Mock or not to Mock
● The Mockist vs The Classicist
● The Mini-integration Tests
● The ObjectMother
● SUT and Collaborator objects
● Ways to Test the service layer:
○ Mock the Repository layer.
○ Use in-memory database.
○ Use a real test database.
30
Testing Spring
Applications
31
Unit Testing
32
Mocks provided by spring
● Environment:
○ MockEnvironment and MockPropertySource
● JNDI
○ SimpleNamingContextBuilder
○ e.g. To bind an embedded datasource to a jndi name
● Servlet api
○ MockHttpServletRequest, MockHttpServletResponse, MockHttpSession, etc.
Exists in package: org.springframework.mock
33
Support Classes
● ReflectionTestUtils
● AopTestUtils
● ModelAndViewAssert
● JdbcTestUtils
34
Integration Testing
35
Integration Testing
● Slower than unit tests.
● Perform some integration testing without requiring application
deployment.
● Exists in package: org.springframework.test
36
Goals of Spring Integration Testing support
● Context Management and Caching
● Dependency Injection of Test Fixtures
● Transaction Management
● Easily executing SQL Scripts
37
Important Annotations
● @ContextConfiguration
● @ActiveProfiles
● @TestPropertySource
● @DirtiesContext
● @Commit & @Rollback
● @BeforeTransaction & @AfterTransaction
● @Sql & @SqlConfig
● @Autowired, @PersistenceContext, @Qualifier, etc.
● @IfProfileValue, @Timed, @Repeat (junit4)
● @SpringJUnitConfig, @EnabledIf, @DisabledIf (junit5)
38
@TestExecutionListeners
● Important component of TestContext framework
● Accepts implementations of TestExecutionListener interface
● Used to implement many of the features
● Example implementations include:
○ ServletTestExecutionListener
○ DependencyInjectionTestExecutionListener
○ DirtiesContextTestExecutionListener
○ TransactionalTestExecutionListener
○ SqlScriptsTestExecutionListener
39
Meta Annotations
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@DisabledIf( expression =
"#{systemProperties['os.name'].toLowerCase().contains('mac')}",
reason = "Disabled on Mac OS")
public @interface DisabledOnMac {}
40
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@ContextConfiguration(classes = {GeoConfig.class})
@ActiveProfiles("dev")
@Transactional
public @interface TransactionalDevGeoTestConfig {}
41
TestContext
Framework
42
JUnit 5 how is different from JUnit4?
● JUnit 4 uses Runner and Rule (TestRule & MethodRule)
○ @RunWith & @Rule
○ Examples:
■ MockitoJUnitRunner
■ SpringRunner
■ MockitoRule
■ WireMockRule
● JUnit 5 uses Extension
○ @ExtendWith
○ Composable
○ Examples:
■ SpringExtension
■ MockitoExtension
43
Spring TestContext is Test-Framework Agnostic
TestContextManager is
the entry point for Test
frameworks (JUnit 4,
JUnit5, TestNG) to the
TestContext framework.
44
Overview
● Support the Integration Testing
goals of spring
● Exists in package:
org.springframework.test.
context
● Core Classes
○ TestContextManager
○ TestContext
○ TestExecutionListener
○ SmartContextLoader
○ TestContextBootstrapper
45
TestContextManager
46
public void beforeTestMethod(Object testInstance, Method testMethod) throws Exception {
String callbackName = "beforeTestMethod";
getTestContext().updateState(testInstance, testMethod, null);
for (TestExecutionListener testExecutionListener : getTestExecutionListeners())
{
try {
testExecutionListener.beforeTestMethod(getTestContext());
}catch (Throwable ex) {
handleBeforeException(ex, callbackName,
testExecutionListener,
testInstance, testMethod);
}
}
} 47
TestContextBootstrapper
● Used to provide the TestContextManager by TestContext and the list
of TestExecutionListener
● You can customize using @BootstrapWith
● @SpringBootTest is itself annotated with
@BootstrapWith(SpringBootTestContextBootstrapper.class)
48
TestExecutionListener
● By default the following listeners are registered:
○ ServletTestExecutionListener
○ DirtiesContextBeforeModesTestExecutionListener
○ DependencyInjectionTestExecutionListener
○ DirtiesContextTestExecutionListener
○ TransactionalTestExecutionListener
○ SqlScriptsTestExecutionListener
● You can customize using @TestExecutionListeners or using
SpringFactoriesLoader mechanism.
● beware not to override default configured listeners
49
Features of
TestContext
50
Context Management
● Provide Context Loading from XML, Groovy and Annotated Classes
Example:
@ContextConfiguration(locations={"/app-config.xml", "/test-
config.xml"})
● Provide Context Initialization using classes implementation
ApplicationContextInitializer
● Provide Caching for the loaded Context between tests
● Can evict the cache using @DirtiesContext
51
@RunWith(SpringRunner.class)
@ContextConfiguration
public class OrderServiceTest {
@Configuration
static class Config {
@Bean
public OrderService orderService() {
OrderService orderService = new OrderServiceImpl();
return orderService;
}
}
@Autowired
private OrderService orderService;
@Test
public void testOrderService() {
// test the orderService
}
} 52
Dependency Injection
● Implemented using DependencyInjectionTestExecutionListener
● Can use setter injection or field injection
● JUnit 5 you can use constructor injection
● Uses @Autowired or @Inject
53
Transaction Management
● Implemented using TransactionalTestExecutionListener.
● PlatformTransactionManager should exist in ApplicationContext
(auto-configured in spring boot).
● Must declare Spring @Transactional on test class or method.
● Cause test method transactions to rolled-back by default.
● Before and After Test callbacks are included in the transaction.
● Differentiate between Spring-managed and application-managed
transactions vs test-managed transactions
54
Transaction Management
● Use @Commit to force commit the transaction
● Use @BeforeTransaction and @AfterTransaction to run out-of-
transaction (it runs before Before and after After)
● o.s.t.c.transaction.TestTransaction could be used to run
programmed transactions
55
@DataJpaTest
@Transactional
@RunWith(SpringRunner::class)
class AccountRepositoryTest {
@Autowired
lateinit var accountRepository: AccountRepository
@Autowired
lateinit var entityManager: TestEntityManager
@Test
fun `test check balance never returns null for a valid account`() {
// Arrange
val account = Account()
entityManager.persist(account)
entityManager.flush() // to avoid false positives
// Act
val balance = accountRepository.checkBalance(account.id)
// Assert
assertThat(balance).isEqualTo(0.0)
}
}
56
Executing SQL Scripts
● @Sql implemented using SqlScriptsTestExecutionListener which
delegates to ResourceDatabasePopulator
● ResourceDatabasePopulator also used by spring boot auto-
configurations ("spring.datasource.schema" and
"spring.datasource.data")
● ResourceDatabasePopulator delegates to
o.s.jdbc.datasource.init.ScriptUtils
57
@SpringJUnitConfig // Junit 5
@Sql("/test-schema.sql")
class DatabaseTests {
@Test
@Sql(scripts="/test-schema.sql", config=@SqlConfig(commentPrefix =
"`"))
@Sql("/test-user-data.sql")
void userTest {
// test code here
}
}
58
Spring MVC Test Framework
● Built on the Servlet API mock objects
● Does not use a running Servlet container
● Why not pure Unit test is not enough? Need to test request mapping,
conversion, validation, etc.
● Two ways to create MockMvc:
○ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
○ this.mockMvc = MockMvcBuilders.standaloneSetup(new
AccountController()).build();
59
@Autowired
private MockMvc mockMvc; // auto-configured by spring boot
@MockBean
private AccountService accountService;
@Test
public void testDepositInvalidInput() throws Exception {
// ....
this.mockMvc.perform(put("/api/v1/account/1/balance/deposit")
.content(jsonObject.toString())
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andDo(print())
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.key")
.value("input.invalid.amountDto.amount.NotNull"));
}
60
Client-Side REST Tests
// Arrange
RestTemplate restTemplate = new RestTemplate()
MockRestServiceServer server =
MockRestServiceServer.bindTo(restTemplate).build();
server.expect(times(1),
requestTo("/hotels/42")).andExpect(method(HttpMethod.GET))
.andRespond(withSuccess("{ "id" : "42", "name" : "Holiday Inn"}",
MediaType.APPLICATION_JSON));
// Act
HotelService hotelService = new HotelService(restTemplate);
Hotel hotel = hotelService.findById(4); //should call the /hotels/42 endpoint
// Assert
server.verify();
61
Features of
Spring boot
62
Helpful Tools
● spring-boot-starter-test brings:
○ JUnit
○ Spring-Test
○ AssertJ: A fluent assertion library.
○ Hamcrest: A library of matcher objects (also known as constraints or predicates).
○ Mockito: A Java mocking framework.
○ JSONassert: An assertion library for JSON.
○ JsonPath: XPath for JSON.
63
Overview
● Use @SpringBootTest instead of @ContextConfiguration.
● By default @SpringBootTest run in MOCK environment
● Search for configurations automatically, no need to configure it manually.
○ - It search for classes annotated by @SpringBootApplication or
@SpringBootConfiguration.
● you can use nested @TestConfiguration to customize the primary
configuration.
● Use @MockBean to define Mockito mocks for beans inside the
ApplicationContext (mocking in integration tests)
64
Overview
● Can do real end-to-end servlet test using TestRestTemplate or
WebTestClient with @SpringBootTest(webEnvironment =
WebEnvironment.RANDOM_PORT)
○ Provide assertions similar to MockMvc
○ Can use REST Assured api as well
65
Testing Slices
● Configured in spring-boot-test-autoconfigure
● Load part of the application configurations/components
● You cannot use multiple slices together, but can @...Test one and
@AutoConfigure... or @ImportAutoConfiguration the others.
● Loads the corresponding Auto Configurations and beans
○ Example, @WebMvcTests does not regular @Componenet classes
66
Testing Slices
● Testing Slices support:
○ @JsonTest
○ @WebMvcTest
○ @WebFluxTest
○ @DataJpaTest
○ @DataRedisTest
○ @RestClientTest
○ ...
67
Demo
68
git clone https://github.com/mhewedy/primitive-bank.git
Extras
69
Using kotlin to write Tests?
70
References
● Test-Driven Development by Example
● Pragmatic Unit Testing in Java with JUnit
● https://blog.cleancoder.com/uncle-bob/2014/05/14/TheLittleMocker.html
● https://www.martinfowler.com/bliki/TestPyramid.html
● https://martinfowler.com/articles/mocksArentStubs.html
● https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html
● https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-
testing.html
● https://www.petrikainulainen.net/programming/testing/writing-clean-tests-to-verify-or-
not-to-verify/
71

More Related Content

What's hot

Building a REST Service in minutes with Spring Boot
Building a REST Service in minutes with Spring BootBuilding a REST Service in minutes with Spring Boot
Building a REST Service in minutes with Spring BootOmri Spector
 
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlJava Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlArjun Thakur
 
Surviving the Java Deserialization Apocalypse // OWASP AppSecEU 2016
Surviving the Java Deserialization Apocalypse // OWASP AppSecEU 2016Surviving the Java Deserialization Apocalypse // OWASP AppSecEU 2016
Surviving the Java Deserialization Apocalypse // OWASP AppSecEU 2016Christian Schneider
 
Java Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepGuo Albert
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework Serhat Can
 
Spring framework in depth
Spring framework in depthSpring framework in depth
Spring framework in depthVinay Kumar
 
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
 
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with ThymeleafSpring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with ThymeleafThymeleaf
 
Spring Framework - Core
Spring Framework - CoreSpring Framework - Core
Spring Framework - CoreDzmitry Naskou
 
Java Thread Synchronization
Java Thread SynchronizationJava Thread Synchronization
Java Thread SynchronizationBenj Del Mundo
 

What's hot (20)

Building a REST Service in minutes with Spring Boot
Building a REST Service in minutes with Spring BootBuilding a REST Service in minutes with Spring Boot
Building a REST Service in minutes with Spring Boot
 
Introduction to java 8 stream api
Introduction to java 8 stream apiIntroduction to java 8 stream api
Introduction to java 8 stream api
 
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of ControlJava Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
 
Spring Security 5
Spring Security 5Spring Security 5
Spring Security 5
 
Surviving the Java Deserialization Apocalypse // OWASP AppSecEU 2016
Surviving the Java Deserialization Apocalypse // OWASP AppSecEU 2016Surviving the Java Deserialization Apocalypse // OWASP AppSecEU 2016
Surviving the Java Deserialization Apocalypse // OWASP AppSecEU 2016
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Java Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By StepJava Persistence API (JPA) Step By Step
Java Persistence API (JPA) Step By Step
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework
 
Java 8 features
Java 8 featuresJava 8 features
Java 8 features
 
Spring framework in depth
Spring framework in depthSpring framework in depth
Spring framework in depth
 
Web api
Web apiWeb api
Web api
 
Spring Web MVC
Spring Web MVCSpring Web MVC
Spring Web MVC
 
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
 
Java 8 Workshop
Java 8 WorkshopJava 8 Workshop
Java 8 Workshop
 
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with ThymeleafSpring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
 
Spring Data JPA
Spring Data JPASpring Data JPA
Spring Data JPA
 
Spring Framework - Core
Spring Framework - CoreSpring Framework - Core
Spring Framework - Core
 
Introduction to GraphQL
Introduction to GraphQLIntroduction to GraphQL
Introduction to GraphQL
 
Java Thread Synchronization
Java Thread SynchronizationJava Thread Synchronization
Java Thread Synchronization
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 

Similar to Testing Spring Applications

Testing in FrontEnd World by Nikita Galkin
Testing in FrontEnd World by Nikita GalkinTesting in FrontEnd World by Nikita Galkin
Testing in FrontEnd World by Nikita GalkinSigma Software
 
Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"Fwdays
 
Plone testingdzug tagung2010
Plone testingdzug tagung2010Plone testingdzug tagung2010
Plone testingdzug tagung2010Timo Stollenwerk
 
Strategy-driven Test Generation with Open Source Frameworks
Strategy-driven Test Generation with Open Source FrameworksStrategy-driven Test Generation with Open Source Frameworks
Strategy-driven Test Generation with Open Source FrameworksDimitry Polivaev
 
Behaviour Driven Development and Thinking About Testing
Behaviour Driven Development and Thinking About TestingBehaviour Driven Development and Thinking About Testing
Behaviour Driven Development and Thinking About Testingdn
 
Bdd and-testing
Bdd and-testingBdd and-testing
Bdd and-testingmalcolmt
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testingpleeps
 
Advanced Dagger talk from 360andev
Advanced Dagger talk from 360andevAdvanced Dagger talk from 360andev
Advanced Dagger talk from 360andevMike Nakhimovich
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Howsatesgoral
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Knowvilniusjug
 
Writing Tests with the Unity Test Framework
Writing Tests with the Unity Test FrameworkWriting Tests with the Unity Test Framework
Writing Tests with the Unity Test FrameworkPeter Kofler
 
3 WAYS TO TEST YOUR COLDFUSION API -
3 WAYS TO TEST YOUR COLDFUSION API - 3 WAYS TO TEST YOUR COLDFUSION API -
3 WAYS TO TEST YOUR COLDFUSION API - Ortus Solutions, Corp
 
3 WAYS TO TEST YOUR COLDFUSION API
3 WAYS TO TEST YOUR COLDFUSION API3 WAYS TO TEST YOUR COLDFUSION API
3 WAYS TO TEST YOUR COLDFUSION APIGavin Pickin
 
Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)vilniusjug
 
Android testing
Android testingAndroid testing
Android testingSean Tsai
 

Similar to Testing Spring Applications (20)

Test driven development
Test driven developmentTest driven development
Test driven development
 
Testing in FrontEnd World by Nikita Galkin
Testing in FrontEnd World by Nikita GalkinTesting in FrontEnd World by Nikita Galkin
Testing in FrontEnd World by Nikita Galkin
 
Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"Никита Галкин "Testing in Frontend World"
Никита Галкин "Testing in Frontend World"
 
Plone testingdzug tagung2010
Plone testingdzug tagung2010Plone testingdzug tagung2010
Plone testingdzug tagung2010
 
Strategy-driven Test Generation with Open Source Frameworks
Strategy-driven Test Generation with Open Source FrameworksStrategy-driven Test Generation with Open Source Frameworks
Strategy-driven Test Generation with Open Source Frameworks
 
Behaviour Driven Development and Thinking About Testing
Behaviour Driven Development and Thinking About TestingBehaviour Driven Development and Thinking About Testing
Behaviour Driven Development and Thinking About Testing
 
Bdd and-testing
Bdd and-testingBdd and-testing
Bdd and-testing
 
Grails unit testing
Grails unit testingGrails unit testing
Grails unit testing
 
Advanced Dagger talk from 360andev
Advanced Dagger talk from 360andevAdvanced Dagger talk from 360andev
Advanced Dagger talk from 360andev
 
Unit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and HowsUnit Testing - The Whys, Whens and Hows
Unit Testing - The Whys, Whens and Hows
 
Unit testing
Unit testingUnit testing
Unit testing
 
Developer Test - Things to Know
Developer Test - Things to KnowDeveloper Test - Things to Know
Developer Test - Things to Know
 
UPC Testing talk 2
UPC Testing talk 2UPC Testing talk 2
UPC Testing talk 2
 
Writing Tests with the Unity Test Framework
Writing Tests with the Unity Test FrameworkWriting Tests with the Unity Test Framework
Writing Tests with the Unity Test Framework
 
3 WAYS TO TEST YOUR COLDFUSION API -
3 WAYS TO TEST YOUR COLDFUSION API - 3 WAYS TO TEST YOUR COLDFUSION API -
3 WAYS TO TEST YOUR COLDFUSION API -
 
3 WAYS TO TEST YOUR COLDFUSION API
3 WAYS TO TEST YOUR COLDFUSION API3 WAYS TO TEST YOUR COLDFUSION API
3 WAYS TO TEST YOUR COLDFUSION API
 
Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)Developer Tests - Things to Know (Vilnius JUG)
Developer Tests - Things to Know (Vilnius JUG)
 
Android testing
Android testingAndroid testing
Android testing
 
Test Driven Development
Test Driven DevelopmentTest Driven Development
Test Driven Development
 
Unit testing basic
Unit testing basicUnit testing basic
Unit testing basic
 

Recently uploaded

Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 

Recently uploaded (20)

Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 

Testing Spring Applications

  • 1. Testing Spring Applications Riyadh Java Meetup Mohammad Hewedy github.com/mhewedy 1 1
  • 2. Agenda ● Unit Test: What and Why? ● Test Driven Development ● Test Patterns ● Test Doubles ● Testing Spring Applications ○ Unit Testing ○ Integration Testing and the TestContext Framework ○ Slice Testing in Spring boot ● Demo 2
  • 4. 4
  • 5. A unit test is a piece of code written by a developer that exercises a very small, specific area of functionality of the code being tested. Unit tests are performed to prove that a piece of code does what the developer thinks it should do. Pragmatic Unit Testing in Java with JUnit 5
  • 7. ● It will make your designs better. ● Reduce the amount of time you spend debugging. ● Give confidence in the code. ● Make sure code do what you want. ● Do what you want all of the Time. ● Make sure you can depend on code. ● Document your intent. ● Shows how to use your code. ● Avoid any collateral damage 7
  • 11. ● It takes too much time to write the tests? ● It takes too long to run the tests? ● It’s not my job to test my code? ● I’m being paid to write code, not to write tests? ● I feel guilty about putting testers and QA staff out of work? 11
  • 12. Test Pyramid Unit Tests Integration Tests (Service Tests) E2E Tests (UI Tests) Fast Slow 12
  • 13. Characteristics of Good Tests ● Automatic ● Thorough ● Repeatable ● Independent ● Professional ● Speed 13
  • 14. Always, “Spring The Trap” Jim Baird - Adventurer 14
  • 16. class MathTest(TestCase): def test_add(self): math = Math() result = math.add(10, 20) assert_equals(30, result) def test_multiply(self): math = Math() result = math.multiply(10, 20) assert_equals(200, result) class Math: def add(self, x, y): return x + y def multiply(self, x, y): return x * y 16
  • 17. Test Driven Development Red/Green/Refactor Write a test Make it compile Run to see it fails Make it run (see next) Remove Duplicate (Refactor) 17
  • 18. How to “Make it run” (Geen Bar Pattern) 1. Fake it 2. Triangulate 3. Obvious implementation 18
  • 19. Green Bar Pattern in Action 19
  • 20. Test Patterns ● Arrange, Act, Assert. ● Arrange, Assert-not, Act, Assert. ● Given, When, Then. ● Setup, Exercise, Verify, Teardown. 20
  • 21. // spock framework def "test listToString"() { given: def list = Arrays.asList("HELLO", "WORLD") when: def listToString = Util.listToString(list) then: listToString == "HELLOnWORLDn" } https://github.com/mhewedy/spwrap/blob/master/src/test/groovy/spwrap/UtilTest.groovy 21
  • 22. @Unroll def "#testDB : using implicit ResultSet Mapper to map result set"() { given: setup(testDB) when: customerDao.createCustomer0(“Abdullah”, “Mohammad”) def list = customerDao.listCustomers(list) then: 1 == list.size() with(list.get(0)){ “Abdullah” == firstName() “Mohammad” == lastName() } cleanup: cleanup(testDB) where: testDB << [HSQL, MYSQL, SQLServer, ORACLE] } 22 https://github.com/mhewedy/spwrap/blob/master/src/test/groovy/spwrap/DAOIntTest.groovy
  • 24. interface Mailer { Boolean send(String to, String subject); } // billing is SUT billing.bill(cusomer); // mailer is collaborator mailer.send(cusomer.getEmail(), postBillHtmlTemplate); Collaborator object vs SUT 24
  • 25. Dummy class DummyMailer implements Mailer { Boolean send(String to, String subject) { return null; } } 25
  • 26. Stub class SuccessfullySendingMailerStub implements Mailer { Boolean send(String to, String subject) { return true; } } 26
  • 27. Spy class SuccessfullySendingMailerSpy implements Mailer { public int callCount; public String recordedTo; public String recordedSubject; Boolean send(String to, String subject) { this.callCount += 1; this.recordedTo = to; this.recordedSubject = subject; return true; } } 27
  • 28. Mock class SuccessfullySendingMailerMock implements Mailer { private int callCount; private String recordedTo; private String recordedSubject; Boolean send(String to, String subject) { this.callCount += 1; this.recordedTo = to; this.recordedSubject = subject; return true; } boolean verify(String expectedTo, String expectedSubject) { return callCount == 1 && this.recordedTo.equals(expectedTo) && this.recordedSubject.equals(expectedSubject); } } 28
  • 29. Fake class MailerFake implements Mailer { Boolean send(String to, String subject) { return SimulatorDataSource.getMailer() .containsRecord(to, subject); } } 29
  • 30. To Mock or not to Mock ● The Mockist vs The Classicist ● The Mini-integration Tests ● The ObjectMother ● SUT and Collaborator objects ● Ways to Test the service layer: ○ Mock the Repository layer. ○ Use in-memory database. ○ Use a real test database. 30
  • 33. Mocks provided by spring ● Environment: ○ MockEnvironment and MockPropertySource ● JNDI ○ SimpleNamingContextBuilder ○ e.g. To bind an embedded datasource to a jndi name ● Servlet api ○ MockHttpServletRequest, MockHttpServletResponse, MockHttpSession, etc. Exists in package: org.springframework.mock 33
  • 34. Support Classes ● ReflectionTestUtils ● AopTestUtils ● ModelAndViewAssert ● JdbcTestUtils 34
  • 36. Integration Testing ● Slower than unit tests. ● Perform some integration testing without requiring application deployment. ● Exists in package: org.springframework.test 36
  • 37. Goals of Spring Integration Testing support ● Context Management and Caching ● Dependency Injection of Test Fixtures ● Transaction Management ● Easily executing SQL Scripts 37
  • 38. Important Annotations ● @ContextConfiguration ● @ActiveProfiles ● @TestPropertySource ● @DirtiesContext ● @Commit & @Rollback ● @BeforeTransaction & @AfterTransaction ● @Sql & @SqlConfig ● @Autowired, @PersistenceContext, @Qualifier, etc. ● @IfProfileValue, @Timed, @Repeat (junit4) ● @SpringJUnitConfig, @EnabledIf, @DisabledIf (junit5) 38
  • 39. @TestExecutionListeners ● Important component of TestContext framework ● Accepts implementations of TestExecutionListener interface ● Used to implement many of the features ● Example implementations include: ○ ServletTestExecutionListener ○ DependencyInjectionTestExecutionListener ○ DirtiesContextTestExecutionListener ○ TransactionalTestExecutionListener ○ SqlScriptsTestExecutionListener 39
  • 40. Meta Annotations @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @DisabledIf( expression = "#{systemProperties['os.name'].toLowerCase().contains('mac')}", reason = "Disabled on Mac OS") public @interface DisabledOnMac {} 40
  • 41. @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @ContextConfiguration(classes = {GeoConfig.class}) @ActiveProfiles("dev") @Transactional public @interface TransactionalDevGeoTestConfig {} 41
  • 43. JUnit 5 how is different from JUnit4? ● JUnit 4 uses Runner and Rule (TestRule & MethodRule) ○ @RunWith & @Rule ○ Examples: ■ MockitoJUnitRunner ■ SpringRunner ■ MockitoRule ■ WireMockRule ● JUnit 5 uses Extension ○ @ExtendWith ○ Composable ○ Examples: ■ SpringExtension ■ MockitoExtension 43
  • 44. Spring TestContext is Test-Framework Agnostic TestContextManager is the entry point for Test frameworks (JUnit 4, JUnit5, TestNG) to the TestContext framework. 44
  • 45. Overview ● Support the Integration Testing goals of spring ● Exists in package: org.springframework.test. context ● Core Classes ○ TestContextManager ○ TestContext ○ TestExecutionListener ○ SmartContextLoader ○ TestContextBootstrapper 45
  • 47. public void beforeTestMethod(Object testInstance, Method testMethod) throws Exception { String callbackName = "beforeTestMethod"; getTestContext().updateState(testInstance, testMethod, null); for (TestExecutionListener testExecutionListener : getTestExecutionListeners()) { try { testExecutionListener.beforeTestMethod(getTestContext()); }catch (Throwable ex) { handleBeforeException(ex, callbackName, testExecutionListener, testInstance, testMethod); } } } 47
  • 48. TestContextBootstrapper ● Used to provide the TestContextManager by TestContext and the list of TestExecutionListener ● You can customize using @BootstrapWith ● @SpringBootTest is itself annotated with @BootstrapWith(SpringBootTestContextBootstrapper.class) 48
  • 49. TestExecutionListener ● By default the following listeners are registered: ○ ServletTestExecutionListener ○ DirtiesContextBeforeModesTestExecutionListener ○ DependencyInjectionTestExecutionListener ○ DirtiesContextTestExecutionListener ○ TransactionalTestExecutionListener ○ SqlScriptsTestExecutionListener ● You can customize using @TestExecutionListeners or using SpringFactoriesLoader mechanism. ● beware not to override default configured listeners 49
  • 51. Context Management ● Provide Context Loading from XML, Groovy and Annotated Classes Example: @ContextConfiguration(locations={"/app-config.xml", "/test- config.xml"}) ● Provide Context Initialization using classes implementation ApplicationContextInitializer ● Provide Caching for the loaded Context between tests ● Can evict the cache using @DirtiesContext 51
  • 52. @RunWith(SpringRunner.class) @ContextConfiguration public class OrderServiceTest { @Configuration static class Config { @Bean public OrderService orderService() { OrderService orderService = new OrderServiceImpl(); return orderService; } } @Autowired private OrderService orderService; @Test public void testOrderService() { // test the orderService } } 52
  • 53. Dependency Injection ● Implemented using DependencyInjectionTestExecutionListener ● Can use setter injection or field injection ● JUnit 5 you can use constructor injection ● Uses @Autowired or @Inject 53
  • 54. Transaction Management ● Implemented using TransactionalTestExecutionListener. ● PlatformTransactionManager should exist in ApplicationContext (auto-configured in spring boot). ● Must declare Spring @Transactional on test class or method. ● Cause test method transactions to rolled-back by default. ● Before and After Test callbacks are included in the transaction. ● Differentiate between Spring-managed and application-managed transactions vs test-managed transactions 54
  • 55. Transaction Management ● Use @Commit to force commit the transaction ● Use @BeforeTransaction and @AfterTransaction to run out-of- transaction (it runs before Before and after After) ● o.s.t.c.transaction.TestTransaction could be used to run programmed transactions 55
  • 56. @DataJpaTest @Transactional @RunWith(SpringRunner::class) class AccountRepositoryTest { @Autowired lateinit var accountRepository: AccountRepository @Autowired lateinit var entityManager: TestEntityManager @Test fun `test check balance never returns null for a valid account`() { // Arrange val account = Account() entityManager.persist(account) entityManager.flush() // to avoid false positives // Act val balance = accountRepository.checkBalance(account.id) // Assert assertThat(balance).isEqualTo(0.0) } } 56
  • 57. Executing SQL Scripts ● @Sql implemented using SqlScriptsTestExecutionListener which delegates to ResourceDatabasePopulator ● ResourceDatabasePopulator also used by spring boot auto- configurations ("spring.datasource.schema" and "spring.datasource.data") ● ResourceDatabasePopulator delegates to o.s.jdbc.datasource.init.ScriptUtils 57
  • 58. @SpringJUnitConfig // Junit 5 @Sql("/test-schema.sql") class DatabaseTests { @Test @Sql(scripts="/test-schema.sql", config=@SqlConfig(commentPrefix = "`")) @Sql("/test-user-data.sql") void userTest { // test code here } } 58
  • 59. Spring MVC Test Framework ● Built on the Servlet API mock objects ● Does not use a running Servlet container ● Why not pure Unit test is not enough? Need to test request mapping, conversion, validation, etc. ● Two ways to create MockMvc: ○ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); ○ this.mockMvc = MockMvcBuilders.standaloneSetup(new AccountController()).build(); 59
  • 60. @Autowired private MockMvc mockMvc; // auto-configured by spring boot @MockBean private AccountService accountService; @Test public void testDepositInvalidInput() throws Exception { // .... this.mockMvc.perform(put("/api/v1/account/1/balance/deposit") .content(jsonObject.toString()) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andDo(print()) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.key") .value("input.invalid.amountDto.amount.NotNull")); } 60
  • 61. Client-Side REST Tests // Arrange RestTemplate restTemplate = new RestTemplate() MockRestServiceServer server = MockRestServiceServer.bindTo(restTemplate).build(); server.expect(times(1), requestTo("/hotels/42")).andExpect(method(HttpMethod.GET)) .andRespond(withSuccess("{ "id" : "42", "name" : "Holiday Inn"}", MediaType.APPLICATION_JSON)); // Act HotelService hotelService = new HotelService(restTemplate); Hotel hotel = hotelService.findById(4); //should call the /hotels/42 endpoint // Assert server.verify(); 61
  • 63. Helpful Tools ● spring-boot-starter-test brings: ○ JUnit ○ Spring-Test ○ AssertJ: A fluent assertion library. ○ Hamcrest: A library of matcher objects (also known as constraints or predicates). ○ Mockito: A Java mocking framework. ○ JSONassert: An assertion library for JSON. ○ JsonPath: XPath for JSON. 63
  • 64. Overview ● Use @SpringBootTest instead of @ContextConfiguration. ● By default @SpringBootTest run in MOCK environment ● Search for configurations automatically, no need to configure it manually. ○ - It search for classes annotated by @SpringBootApplication or @SpringBootConfiguration. ● you can use nested @TestConfiguration to customize the primary configuration. ● Use @MockBean to define Mockito mocks for beans inside the ApplicationContext (mocking in integration tests) 64
  • 65. Overview ● Can do real end-to-end servlet test using TestRestTemplate or WebTestClient with @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) ○ Provide assertions similar to MockMvc ○ Can use REST Assured api as well 65
  • 66. Testing Slices ● Configured in spring-boot-test-autoconfigure ● Load part of the application configurations/components ● You cannot use multiple slices together, but can @...Test one and @AutoConfigure... or @ImportAutoConfiguration the others. ● Loads the corresponding Auto Configurations and beans ○ Example, @WebMvcTests does not regular @Componenet classes 66
  • 67. Testing Slices ● Testing Slices support: ○ @JsonTest ○ @WebMvcTest ○ @WebFluxTest ○ @DataJpaTest ○ @DataRedisTest ○ @RestClientTest ○ ... 67
  • 70. Using kotlin to write Tests? 70
  • 71. References ● Test-Driven Development by Example ● Pragmatic Unit Testing in Java with JUnit ● https://blog.cleancoder.com/uncle-bob/2014/05/14/TheLittleMocker.html ● https://www.martinfowler.com/bliki/TestPyramid.html ● https://martinfowler.com/articles/mocksArentStubs.html ● https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html ● https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features- testing.html ● https://www.petrikainulainen.net/programming/testing/writing-clean-tests-to-verify-or- not-to-verify/ 71

Editor's Notes

  1. Automatic: In Invoking the tests In Checking the results That the test must determine for itself whether it passed or failed. This idea of having the tests run by themselves and check themselves is critical, because it means that you don’t have to think about it—it just happens as part of the project Throught: Test everything that’s likely break based on the needs of your project Repeatable: independent of the environment run over and over again, in any order, and produce the same results. Independent: testing one thing at a time independent from the environment and each other Independent also means that no test relies on any other test Professional: written and maintained to the same professional standards as your production code code reuse.
  2. cause the production code to exhibit the very bug you’re trying to detect, and verify that the test fails as expected. Steps when fix a bug: 1. Identify the bug. 2. Write a test that fails, to prove the bug exists. 3. Fix the code such that the test now passes. 4. Verify that all tests still pass (i.e., you didn’t break anything else as a result of the fix
  3. - @ContextConfiguration <<inheritable>> <<load additional test configuration, ApplicationContextInitializer or configure ContextLoader>> - @ActiveProfiles <<inheritable>> - @TestPropertySource <<class level>> - @TestExecutionListeners: TestExecutionListener: beforeTestClass prepareTestInstance beforeTestExecution beforeTestMethod afterTestExecution afterTestMethod afterTestClass examples: ServletTestExecutionListener DependencyInjectionTestExecutionListener DirtiesContextTestExecutionListener TransactionalTestExecutionListener SqlScriptsTestExecutionListener - @DirtiesContext: DirtiesContextTestExecutionListener <<class&method level>> - @BootstrapWith TestContextBootstraper - @Commit & @Rollback: TransactionalTestExecutionListener - @BeforeTransaction & @AfterTransaction: TransactionalTestExecutionListener - @Sql & @SqlConfig: SqlScriptsTestExecutionListener - @Autowired, @PersistenceContext, @Qualifier, etc. : DependencyInjectionTestExecutionListener - @IfProfileValue, @Timed, @Repeat (junit4) - @SpringJUnitConfig, @EnabledIf, @DisabledIf (junit5)
  4. TestContextManager is independent of the Underlying Test framework It is being used by JUnit 5 by being used by SpringExtensions JUnit 5 Extension And used by JUnit 4 via Rules (SpringMethodRule) and Runners (Spring JUnit4ClassRunner) via the RunBeforeTestMethodCallbacks