SlideShare ist ein Scribd-Unternehmen logo
1 von 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

Weitere ähnliche Inhalte

Was ist angesagt?

Spring framework IOC and Dependency Injection
Spring framework  IOC and Dependency InjectionSpring framework  IOC and Dependency Injection
Spring framework IOC and Dependency InjectionAnuj Singh Rajput
 
Spring framework Introduction
Spring framework IntroductionSpring framework Introduction
Spring framework IntroductionAnuj Singh Rajput
 
2 TomcatによるWebアプリケーションサーバ構築 第3章 Apacheの構成
2 TomcatによるWebアプリケーションサーバ構築 第3章 Apacheの構成2 TomcatによるWebアプリケーションサーバ構築 第3章 Apacheの構成
2 TomcatによるWebアプリケーションサーバ構築 第3章 Apacheの構成Enpel
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring FrameworkASG
 
Reflection in java
Reflection in javaReflection in java
Reflection in javaupen.rockin
 
Introduction to Testcontainers
Introduction to TestcontainersIntroduction to Testcontainers
Introduction to TestcontainersVMware Tanzu
 
Whitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsWhitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsYura Nosenko
 
Introduction to Aspect Oriented Programming
Introduction to Aspect Oriented ProgrammingIntroduction to Aspect Oriented Programming
Introduction to Aspect Oriented ProgrammingAmir Kost
 
Advance Java Topics (J2EE)
Advance Java Topics (J2EE)Advance Java Topics (J2EE)
Advance Java Topics (J2EE)slire
 
The Many Ways to Test Your React App
The Many Ways to Test Your React AppThe Many Ways to Test Your React App
The Many Ways to Test Your React AppAll Things Open
 
Reactive programming
Reactive programmingReactive programming
Reactive programmingSUDIP GHOSH
 
The Art of Metaprogramming in Java
The Art of Metaprogramming in Java  The Art of Metaprogramming in Java
The Art of Metaprogramming in Java Abdelmonaim Remani
 
Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot IntroductionJeevesh Pandey
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced JavascriptAdieu
 

Was ist angesagt? (20)

Spring AOP
Spring AOPSpring AOP
Spring AOP
 
Java 17
Java 17Java 17
Java 17
 
Spring framework IOC and Dependency Injection
Spring framework  IOC and Dependency InjectionSpring framework  IOC and Dependency Injection
Spring framework IOC and Dependency Injection
 
Spring Boot
Spring BootSpring Boot
Spring Boot
 
Spring framework Introduction
Spring framework IntroductionSpring framework Introduction
Spring framework Introduction
 
2 TomcatによるWebアプリケーションサーバ構築 第3章 Apacheの構成
2 TomcatによるWebアプリケーションサーバ構築 第3章 Apacheの構成2 TomcatによるWebアプリケーションサーバ構築 第3章 Apacheの構成
2 TomcatによるWebアプリケーションサーバ構築 第3章 Apacheの構成
 
Introduction to Spring Framework
Introduction to Spring FrameworkIntroduction to Spring Framework
Introduction to Spring Framework
 
Generics in java
Generics in javaGenerics in java
Generics in java
 
Reflection in java
Reflection in javaReflection in java
Reflection in java
 
Introduction to Testcontainers
Introduction to TestcontainersIntroduction to Testcontainers
Introduction to Testcontainers
 
Introduction to spring boot
Introduction to spring bootIntroduction to spring boot
Introduction to spring boot
 
Whitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applicationsWhitebox testing of Spring Boot applications
Whitebox testing of Spring Boot applications
 
Introduction to Aspect Oriented Programming
Introduction to Aspect Oriented ProgrammingIntroduction to Aspect Oriented Programming
Introduction to Aspect Oriented Programming
 
Advance Java Topics (J2EE)
Advance Java Topics (J2EE)Advance Java Topics (J2EE)
Advance Java Topics (J2EE)
 
The Many Ways to Test Your React App
The Many Ways to Test Your React AppThe Many Ways to Test Your React App
The Many Ways to Test Your React App
 
Reactive programming
Reactive programmingReactive programming
Reactive programming
 
The Art of Metaprogramming in Java
The Art of Metaprogramming in Java  The Art of Metaprogramming in Java
The Art of Metaprogramming in Java
 
Spring notes
Spring notesSpring notes
Spring notes
 
Spring boot Introduction
Spring boot IntroductionSpring boot Introduction
Spring boot Introduction
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
 

Ähnlich wie 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
 

Ähnlich wie 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
 

Kürzlich hochgeladen

SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
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
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
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
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
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
 
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
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
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
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
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.
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 

Kürzlich hochgeladen (20)

Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
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
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
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
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
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...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
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
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
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...
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
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...
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 

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

Hinweis der Redaktion

  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