JUnit in Action [3 ed.]
1617297046, 9781617297045
JUnit is the gold standard for unit testing Java applications. Filled with powerful new features designed to automate so
480
72
28MB
English
Pages 560
[562]
Year 2020
Report DMCA / Copyright
DOWNLOAD PDF FILE
Table of contents :
JUnit in Action
contents
preface
acknowledgments
about this book
Who should read this book
How this book is organized: A roadmap
About the code
liveBook discussion forum
about the author
about the cover illustration
Part 1 JUnit
1 JUnit jump-start
1.1 Proving that a program works
1.2 Starting from scratch
1.2.1 Understanding unit testing frameworks
1.2.2 Adding unit tests
1.3 Setting up JUnit
1.4 Testing with JUnit
Summary
2 Exploring core JUnit
2.1 Core annotations
2.1.1 The @DisplayName annotation
2.1.2 The @Disabled annotation
2.2 Nested tests
2.3 Tagged tests
2.4 Assertions
2.5 Assumptions
2.6 Dependency injection in JUnit 5
2.6.1 TestInfoParameterResolver
2.6.2 TestReporterParameterResolver
2.6.3 RepetitionInfoParameterResolver
2.7 Repeated tests
2.8 Parameterized tests
2.9 Dynamic tests
2.10 Using Hamcrest matchers
Summary
3 JUnit architecture
3.1 The concept and importance of software architecture
3.1.1 Story 1: The telephone directories
3.1.2 Story 2: The sneakers manufacturer
3.2 The JUnit 4 architecture
3.2.1 JUnit 4 modularity
3.2.2 JUnit 4 runners
3.2.3 JUnit 4 rules
3.2.4 Shortcomings of the JUnit 4 architecture
3.3 The JUnit 5 architecture
3.3.1 JUnit 5 modularity
3.3.2 JUnit Platform
3.3.3 JUnit Jupiter
3.3.4 JUnit Vintage
3.3.5 The big picture of the JUnit 5 architecture
Summary
4 Migrating from JUnit 4 to JUnit 5
4.1 Migration steps between JUnit 4 and JUnit 5
4.2 Needed dependencies
4.3 Annotations, classes, and methods
4.3.1 Equivalent annotations, classes, and methods
4.3.2 Categories vs. tags
4.3.3 Migrating Hamcrest matcher functionality
4.3.4 Rules vs. the extension model
4.3.5 Custom rules
Summary
5 Software testing principles
5.1 The need for unit tests
5.1.1 Allowing greater test coverage
5.1.2 Increasing team productivity
5.1.3 Detecting regressions and limiting debugging
5.1.4 Refactoring with confidence
5.1.5 Improving implementation
5.1.6 Documenting expected behavior
5.1.7 Enabling code coverage and other metrics
5.2 Test types
5.2.1 Unit testing
5.2.2 Integration software testing
5.2.3 System software testing
5.2.4 Acceptance software testing
5.3 Black-box vs. white-box testing
5.3.1 Black-box testing
5.3.2 White-box testing
5.3.3 Pros and cons
Summary
Part 2 Different testing strategies
6 Test quality
6.1 Measuring test coverage
6.1.1 Introduction to test coverage
6.1.2 Tools for measuring code coverage
6.2 Writing testable code
6.2.1 Understanding that public APIs are contracts
6.2.2 Reducing dependencies
6.2.3 Creating simple constructors
6.2.4 Following the Law of Demeter (Principle of Least Knowledge)
6.2.5 Avoiding hidden dependencies and global state
6.2.6 Favoring generic methods
6.2.7 Favoring composition over inheritance
6.2.8 Favoring polymorphism over conditionals
6.3 Test-driven development
6.3.1 Adapting the development cycle
6.3.2 Doing the TDD two-step
6.4 Behavior-driven development
6.5 Mutation testing
6.6 Testing in the development cycle
Summary
7 Coarse-grained testing with stubs
7.1 Introducing stubs
7.2 Stubbing an HTTP connection
7.2.1 Choosing a stubbing solution
7.2.2 Using Jetty as an embedded server
7.3 Stubbing the web server resources
7.3.1 Setting up the first stub test
7.3.2 Reviewing the first stub test
7.4 Stubbing the connection
7.4.1 Producing a custom URL protocol handler
7.4.2 Creating a JDK HttpURLConnection stub
7.4.3 Running the test
Summary
8 Testing with mock objects
8.1 Introducing mock objects
8.2 Unit testing with mock objects
8.3 Refactoring with mock objects
8.3.1 Refactoring example
8.3.2 Refactoring considerations
8.4 Mocking an HTTP connection
8.4.1 Defining the mock objects
8.4.2 Testing a sample method
8.4.3 Try #1: Easy refactoring technique
8.4.4 Try #2: Refactoring by using a class factory
8.5 Using mocks as Trojan horses
8.6 Introducing mock frameworks
8.6.1 Using EasyMock
8.6.2 Using JMock
8.6.3 Using Mockito
Summary
9 In-container testing
9.1 Limitations of standard unit testing
9.2 The mock-objects solution
9.3 The step to in-container testing
9.3.1 Implementation strategies
9.3.2 In-container testing frameworks
9.4 Comparing stubs, mock objects, and in-container testing
9.4.1 Stubs evaluation
9.4.2 Mock-objects evaluation
9.4.3 In-container testing evaluation
9.5 Testing with Arquillian
Summary
Part 3 Working with JUnit 5 and other tools
10 Running JUnit tests from Maven 3
10.1 Setting up a Maven project
10.2 Using the Maven plugins
10.2.1 Maven compiler plugin
10.2.2 Maven Surefire plugin
10.2.3 Generating HTML JUnit reports with Maven
10.3 Putting it all together
10.4 Maven challenges
Summary
11 Running JUnit tests from Gradle 6
11.1 Introducing Gradle
11.2 Setting up a Gradle project
11.3 Using Gradle plugins
11.4 Creating a Gradle project from scratch and testing it with JUnit 5
11.5 Comparing Gradle and Maven
Summary
12 JUnit 5 IDE support
12.1 Using JUnit 5 with IntelliJ IDEA
12.2 Using JUnit 5 with Eclipse
12.3 Using JUnit 5 with NetBeans
12.4 Comparing JUnit 5 usage in IntelliJ, Eclipse, and NetBeans
Summary
13 Continuous integration with JUnit 5
13.1 Continuous integration testing
13.2 Introducing Jenkins
13.3 Practicing CI on a team
13.4 Configuring Jenkins
13.5 Working on tasks in a CI environment
Summary
Part 4 Working with modern frameworks and JUnit 5
14 JUnit 5 extension model
14.1 Introducing the JUnit 5 extension model
14.2 Creating a JUnit 5 extension
14.3 Writing JUnit 5 tests using the available extension points
14.3.1 Persisting passengers to a database
14.3.2 Checking the uniqueness of passengers
Summary
15 Presentation-layer testing
15.1 Choosing a testing framework
15.2 Introducing HtmlUnit
15.2.1 A live example
15.3 Writing HtmlUnit tests
15.3.1 HTML assertions
15.3.2 Testing for a specific web browser
15.3.3 Testing more than one web browser
15.3.4 Creating standalone tests
15.3.5 Testing forms
15.3.6 Testing JavaScript
15.4 Introducing Selenium
15.5 Writing Selenium tests
15.5.1 Testing for a specific web browser
15.5.2 Testing navigation using a web browser
15.5.3 Testing more than one web browser
15.5.4 Testing Google search and navigation using different web browsers
15.5.5 Testing website authentication
15.6 HtmlUnit vs. Selenium
Summary
16 Testing Spring applications
16.1 Introducing the Spring Framework
16.2 Introducing dependency injection
16.3 Using and testing a Spring application
16.3.1 Creating the Spring context programmatically
16.3.2 Using the Spring TestContext framework
16.4 Using SpringExtension for JUnit Jupiter
16.5 Adding a new feature and testing it with JUnit 5
Summary
17 Testing Spring Boot applications
17.1 Introducing Spring Boot
17.2 Creating a project with Spring Initializr
17.3 Moving the Spring application to Spring Boot
17.4 Implementing a test-specific configuration for Spring Boot
17.5 Adding and testing a new feature in the Spring Boot application
Summary
18 Testing a REST API
18.1 Introducing REST applications
18.2 Creating a RESTful API to manage one entity
18.3 Creating a RESTful API to manage two related entities
18.4 Testing the RESTful API
Summary
19 Testing database applications
19.1 The database unit testing impedance mismatch
19.1.1 Unit tests must exercise code in isolation
19.1.2 Unit tests must be easy to write and run
19.1.3 Unit tests must be fast to run
19.2 Testing a JDBC application
19.3 Testing a Spring JDBC application
19.4 Testing a Hibernate application
19.5 Testing a Spring Hibernate application
19.6 Comparing the approaches for testing database applications
Summary
Part 5 Developing applications with JUnit 5
20 Test-driven development with JUnit 5
20.1 TDD main concepts
20.2 The flight-management application
20.3 Preparing the flight-management application for TDD
20.4 Refactoring the flight-management application
20.5 Introducing new features using TDD
20.5.1 Adding a premium flight
20.5.2 Adding a passenger only once
Summary
21 Behavior-driven development with JUnit 5
21.1 Introducing behavior-driven development
21.1.1 Introducing a new feature
21.1.2 From requirements analysis to acceptance criteria
21.1.3 BDD benefits and challenges
21.2 Working BDD style with Cucumber and JUnit 5
21.2.1 Introducing Cucumber
21.2.2 Moving a TDD feature to Cucumber
21.2.3 Adding a new feature with the help of Cucumber
21.3 Working BDD style with JBehave and JUnit 5
21.3.1 Introducing JBehave
21.3.2 Moving a TDD feature to JBehave
21.3.3 Adding a new feature with the help of JBehave
21.4 Comparing Cucumber and JBehave
Summary
22 Implementing a test pyramid strategy with JUnit 5
22.1 Software testing levels
22.2 Unit testing: Basic components working in isolation
22.3 Integration testing: Units combined into a group
22.4 System testing: Looking at the complete software
22.4.1 Testing with a mock external dependency
22.4.2 Testing with a partially implemented external dependency
22.4.3 Testing with the fully implemented external dependency
22.5 Acceptance testing: Compliance with business requirements
Summary
appendix A Maven
A.1 Convention over configuration
A.2 Strong dependency management
A.3 Maven build life cycles
A.4 Plugin-based architecture
A.5 The Maven project object model (POM)
A.6 Installing Maven
appendix B Gradle
B.1 Installing Gradle
B.2 Creating Gradle tasks
appendix C IDEs
C.1 Installing IntelliJ IDEA
C.2 Installing Eclipse
C.3 Installing NetBeans
appendix D Jenkins
index
Symbols
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
JUnit in Action - back