renamed back to testing-modules, pulled together testing-modules-2 modules into single module

This commit is contained in:
Sjmillington
2019-09-04 18:03:26 +01:00
parent ff871516ee
commit ce9ea390ba
558 changed files with 16 additions and 75 deletions

View File

@@ -0,0 +1,5 @@
## Testing Modules
This is a aggregator module containing several modules focused on testing libraries.

View File

@@ -0,0 +1,3 @@
## Relevant Articles:
- [Quick Guide to EasyRandom in Java](https://www.baeldung.com/java-easy-random)

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>easy-random</artifactId>
<name>easy-random</name>
<parent>
<artifactId>parent-modules</artifactId>
<groupId>com.baeldung</groupId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.jeasy</groupId>
<artifactId>easy-random-core</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,17 @@
package org.baeldung.easy.random.model;
import java.util.StringJoiner;
public class Department {
private String depName;
public Department(String depName) {
this.depName = depName;
}
@Override
public String toString() {
return new StringJoiner(", ", Department.class.getSimpleName() + "[", "]").add("depName='" + depName + "'")
.toString();
}
}

View File

@@ -0,0 +1,70 @@
package org.baeldung.easy.random.model;
import java.util.*;
public class Employee {
private long id;
private String firstName;
private String lastName;
private Department department;
private Collection<Employee> coworkers;
private Map<YearQuarter, Grade> quarterGrades;
public Employee(long id, String firstName, String lastName, Department department) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.department = department;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Employee employee = (Employee) o;
return id == employee.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public long getId() {
return id;
}
public Department getDepartment() {
return department;
}
public Collection<Employee> getCoworkers() {
return Collections.unmodifiableCollection(coworkers);
}
public Map<YearQuarter, Grade> getQuarterGrades() {
return Collections.unmodifiableMap(quarterGrades);
}
@Override
public String toString() {
return new StringJoiner(", ", Employee.class.getSimpleName() + "[", "]").add("id=" + id)
.add("firstName='" + firstName + "'")
.add("lastName='" + lastName + "'")
.add("department=" + department)
.add("coworkers size=" + ((coworkers == null) ? 0 : coworkers.size()))
.add("quarterGrades=" + quarterGrades)
.toString();
}
}

View File

@@ -0,0 +1,22 @@
package org.baeldung.easy.random.model;
import java.util.StringJoiner;
public class Grade {
private int grade;
public Grade(int grade) {
this.grade = grade;
}
public int getGrade() {
return grade;
}
@Override
public String toString() {
return new StringJoiner(", ", Grade.class.getSimpleName() + "[", "]").add("grade=" + grade)
.toString();
}
}

View File

@@ -0,0 +1,30 @@
package org.baeldung.easy.random.model;
import java.util.StringJoiner;
public class Person {
private String firstName;
private String lastName;
private Integer age;
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public Integer getAge() {
return age;
}
@Override
public String toString() {
return new StringJoiner(", ", Person.class.getSimpleName() + "[", "]").add("firstName='" + firstName + "'")
.add("lastName='" + lastName + "'")
.add("age=" + age)
.toString();
}
}

View File

@@ -0,0 +1,50 @@
package org.baeldung.easy.random.model;
import java.time.LocalDate;
import java.util.Objects;
import java.util.StringJoiner;
public class YearQuarter {
private LocalDate startDate;
private LocalDate endDate;
public YearQuarter(LocalDate startDate) {
this.startDate = startDate;
autoAdjustEndDate();
}
private void autoAdjustEndDate() {
endDate = startDate.plusMonths(3L);
}
public LocalDate getStartDate() {
return startDate;
}
public LocalDate getEndDate() {
return endDate;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
YearQuarter quarter = (YearQuarter) o;
return Objects.equals(startDate, quarter.startDate) && Objects.equals(endDate, quarter.endDate);
}
@Override
public int hashCode() {
return Objects.hash(startDate, endDate);
}
@Override
public String toString() {
return new StringJoiner(", ", YearQuarter.class.getSimpleName() + "[", "]").add("startDate=" + startDate)
.add("endDate=" + endDate)
.toString();
}
}

View File

@@ -0,0 +1,18 @@
package org.baeldung.easy.random.randomizer;
import org.baeldung.easy.random.model.YearQuarter;
import org.jeasy.random.api.Randomizer;
import java.time.LocalDate;
import java.time.Month;
public class YearQuarterRandomizer implements Randomizer<YearQuarter> {
private LocalDate date = LocalDate.of(1990, Month.SEPTEMBER, 25);
@Override
public YearQuarter getRandomValue() {
date = date.plusMonths(3);
return new YearQuarter(date);
}
}

View File

@@ -0,0 +1,63 @@
package org.baeldung.easy.random;
import org.baeldung.easy.random.model.Employee;
import org.baeldung.easy.random.model.Person;
import org.baeldung.easy.random.model.YearQuarter;
import org.baeldung.easy.random.randomizer.YearQuarterRandomizer;
import org.jeasy.random.EasyRandom;
import org.jeasy.random.EasyRandomParameters;
import org.jeasy.random.FieldPredicates;
import org.jeasy.random.TypePredicates;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.*;
class EasyRandomUnitTest {
@Test
void givenDefaultConfiguration_thenGenerateSingleObject() {
EasyRandom generator = new EasyRandom();
Person person = generator.nextObject(Person.class);
assertNotNull(person.getAge());
assertNotNull(person.getFirstName());
assertNotNull(person.getLastName());
}
@Test
void givenDefaultConfiguration_thenGenerateObjectsList() {
EasyRandom generator = new EasyRandom();
List<Person> persons = generator.objects(Person.class, 5)
.collect(Collectors.toList());
assertEquals(5, persons.size());
}
@Test
void givenCustomConfiguration_thenGenerateSingleEmployee() {
EasyRandomParameters parameters = new EasyRandomParameters();
parameters.stringLengthRange(3, 3);
parameters.collectionSizeRange(5, 5);
parameters.excludeField(FieldPredicates.named("lastName").and(FieldPredicates.inClass(Employee.class)));
parameters.excludeType(TypePredicates.inPackage("not.existing.pkg"));
parameters.randomize(YearQuarter.class, new YearQuarterRandomizer());
EasyRandom generator = new EasyRandom(parameters);
Employee employee = generator.nextObject(Employee.class);
assertEquals(3, employee.getFirstName().length());
assertEquals(5, employee.getCoworkers().size());
assertEquals(5, employee.getQuarterGrades().size());
assertNotNull(employee.getDepartment());
assertNull(employee.getLastName());
for (YearQuarter key : employee.getQuarterGrades().keySet()) {
assertEquals(key.getStartDate(), key.getEndDate().minusMonths(3L));
}
}
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<artifactId>easymock</artifactId>
<name>easymock</name>
<url>http://maven.apache.org</url>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>testing-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>${easymock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<easymock.version>4.0.2</easymock.version>
</properties>
</project>

View File

@@ -0,0 +1,28 @@
package com.baeldung.testing.easymock;
import java.math.BigDecimal;
public class ForecastProcessor {
private WeatherService weatherService;
public BigDecimal getMaximumTemperature(String locationName) {
Location location = new Location(locationName);
try {
weatherService.populateTemperature(location);
} catch (ServiceUnavailableException e) {
return null;
}
return location.getMaximumTemparature();
}
public WeatherService getWeatherService() {
return weatherService;
}
public void setWeatherService(WeatherService weatherService) {
this.weatherService = weatherService;
}
}

View File

@@ -0,0 +1,33 @@
package com.baeldung.testing.easymock;
import java.math.BigDecimal;
public class Location {
private String name;
private BigDecimal minimumTemperature;
private BigDecimal maximumTemparature;
public Location(String name) {
this.name = name;
}
public String getName() {
return name;
}
public BigDecimal getMinimumTemperature() {
return minimumTemperature;
}
public void setMinimumTemperature(BigDecimal minimumTemperature) {
this.minimumTemperature = minimumTemperature;
}
public BigDecimal getMaximumTemparature() {
return maximumTemparature;
}
public void setMaximumTemparature(BigDecimal maximumTemparature) {
this.maximumTemparature = maximumTemparature;
}
}

View File

@@ -0,0 +1,7 @@
package com.baeldung.testing.easymock;
public class ServiceUnavailableException extends Exception {
private static final long serialVersionUID = 6961151537340723535L;
}

View File

@@ -0,0 +1,5 @@
package com.baeldung.testing.easymock;
public interface WeatherService {
void populateTemperature(Location location) throws ServiceUnavailableException;
}

View File

@@ -0,0 +1,49 @@
package com.baeldung.testing.easymock;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import java.math.BigDecimal;
import org.easymock.EasyMock;
import org.easymock.EasyMockRule;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
public class ForecastProcessorUnitTest {
private static int MAX_TEMP = 90;
@Rule
public EasyMockRule rule = new EasyMockRule(this);
@TestSubject
private ForecastProcessor forecastProcessor = new ForecastProcessor();
@Mock
private WeatherService mockWeatherService;
@Before
public void setUp() {
forecastProcessor.setWeatherService(mockWeatherService);
}
@SuppressWarnings("unchecked")
@Test
public void givenLocationName_whenWeatherServicePopulatesTemperatures_thenMaxTempReturned() throws ServiceUnavailableException {
mockWeatherService.populateTemperature(EasyMock.anyObject(Location.class));
EasyMock.expectLastCall()
.andAnswer(() -> {
Location passedLocation = (Location) EasyMock.getCurrentArguments()[0];
passedLocation.setMaximumTemparature(new BigDecimal(MAX_TEMP));
passedLocation.setMinimumTemperature(new BigDecimal(MAX_TEMP - 10));
return null;
});
EasyMock.replay(mockWeatherService);
BigDecimal maxTemperature = forecastProcessor.getMaximumTemperature("New York");
EasyMock.verify(mockWeatherService);
assertThat(maxTemperature, equalTo(new BigDecimal(MAX_TEMP)));
}
}

View File

@@ -0,0 +1,5 @@
### Relevant Articles:
- [Intro to Gatling](http://www.baeldung.com/introduction-to-gatling)
### Running a simualtion
- To run a simulation use "simulation" profile, command - `mvn install -Psimulation -Dgib.enabled=false`

View File

@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.baeldung</groupId>
<artifactId>gatling</artifactId>
<version>1.0-SNAPSHOT</version>
<name>gatling</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.gatling</groupId>
<artifactId>gatling-app</artifactId>
<version>${gatling.version}</version>
</dependency>
<dependency>
<groupId>io.gatling</groupId>
<artifactId>gatling-recorder</artifactId>
<version>${gatling.version}</version>
</dependency>
<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>${gatling.version}</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
</dependency>
<dependency>
<groupId>io.gatling</groupId>
<artifactId>gatling-app</artifactId>
</dependency>
<dependency>
<groupId>io.gatling</groupId>
<artifactId>gatling-recorder</artifactId>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
</dependency>
</dependencies>
<build>
<testSourceDirectory>src/test/scala</testSourceDirectory>
<pluginManagement>
<plugins>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>${scala-maven-plugin.version}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<args>
<!--<arg>-Ybackend:GenBCode</arg> -->
<arg>-Ydelambdafy:method</arg>
<arg>-target:jvm-1.8</arg>
<arg>-deprecation</arg>
<arg>-feature</arg>
<arg>-unchecked</arg>
<arg>-language:implicitConversions</arg>
<arg>-language:postfixOps</arg>
</args>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>simulation</id>
<build>
<plugins>
<plugin>
<groupId>io.gatling</groupId>
<artifactId>gatling-maven-plugin</artifactId>
<version>${gatling-maven-plugin.version}</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<disableCompiler>true</disableCompiler>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<encoding>UTF-8</encoding>
<scala.version>2.12.6</scala.version> <!--2.11.12 --> <!--2.12.6 -->
<gatling.version>2.3.1</gatling.version> <!--2.2.5 --> <!--2.3.1 -->
<scala-maven-plugin.version>3.2.2</scala-maven-plugin.version> <!--3.2.2 --> <!--3.3.2 -->
<gatling-maven-plugin.version>2.2.4</gatling-maven-plugin.version> <!--2.2.1 --> <!--2.2.4 -->
</properties>
</project>

View File

@@ -0,0 +1,127 @@
#########################
# Gatling Configuration #
#########################
# This file contains all the settings configurable for Gatling with their default values
gatling {
core {
#outputDirectoryBaseName = "" # The prefix for each simulation result folder (then suffixed by the report generation timestamp)
#runDescription = "" # The description for this simulation run, displayed in each report
#encoding = "utf-8" # Encoding to use throughout Gatling for file and string manipulation
#simulationClass = "" # The FQCN of the simulation to run (when used in conjunction with noReports, the simulation for which assertions will be validated)
#mute = false # When set to true, don't ask for simulation name nor run description (currently only used by Gatling SBT plugin)
#elFileBodiesCacheMaxCapacity = 200 # Cache size for request body EL templates, set to 0 to disable
#rawFileBodiesCacheMaxCapacity = 200 # Cache size for request body Raw templates, set to 0 to disable
#rawFileBodiesInMemoryMaxSize = 1000 # Below this limit, raw file bodies will be cached in memory
extract {
regex {
#cacheMaxCapacity = 200 # Cache size for the compiled regexes, set to 0 to disable caching
}
xpath {
#cacheMaxCapacity = 200 # Cache size for the compiled XPath queries, set to 0 to disable caching
}
jsonPath {
#cacheMaxCapacity = 200 # Cache size for the compiled jsonPath queries, set to 0 to disable caching
#preferJackson = false # When set to true, prefer Jackson over Boon for JSON-related operations
}
css {
#cacheMaxCapacity = 200 # Cache size for the compiled CSS selectors queries, set to 0 to disable caching
}
}
directory {
#data = user-files/data # Folder where user's data (e.g. files used by Feeders) is located
#bodies = user-files/bodies # Folder where bodies are located
#simulations = user-files/simulations # Folder where the bundle's simulations are located
#reportsOnly = "" # If set, name of report folder to look for in order to generate its report
#binaries = "" # If set, name of the folder where compiles classes are located: Defaults to GATLING_HOME/target.
#results = results # Name of the folder where all reports folder are located
}
}
charting {
#noReports = false # When set to true, don't generate HTML reports
#maxPlotPerSeries = 1000 # Number of points per graph in Gatling reports
#useGroupDurationMetric = false # Switch group timings from cumulated response time to group duration.
indicators {
#lowerBound = 800 # Lower bound for the requests' response time to track in the reports and the console summary
#higherBound = 1200 # Higher bound for the requests' response time to track in the reports and the console summary
#percentile1 = 50 # Value for the 1st percentile to track in the reports, the console summary and Graphite
#percentile2 = 75 # Value for the 2nd percentile to track in the reports, the console summary and Graphite
#percentile3 = 95 # Value for the 3rd percentile to track in the reports, the console summary and Graphite
#percentile4 = 99 # Value for the 4th percentile to track in the reports, the console summary and Graphite
}
}
http {
#fetchedCssCacheMaxCapacity = 200 # Cache size for CSS parsed content, set to 0 to disable
#fetchedHtmlCacheMaxCapacity = 200 # Cache size for HTML parsed content, set to 0 to disable
#perUserCacheMaxCapacity = 200 # Per virtual user cache size, set to 0 to disable
#warmUpUrl = "http://gatling.io" # The URL to use to warm-up the HTTP stack (blank means disabled)
#enableGA = true # Very light Google Analytics, please support
ssl {
keyStore {
#type = "" # Type of SSLContext's KeyManagers store
#file = "" # Location of SSLContext's KeyManagers store
#password = "" # Password for SSLContext's KeyManagers store
#algorithm = "" # Algorithm used SSLContext's KeyManagers store
}
trustStore {
#type = "" # Type of SSLContext's TrustManagers store
#file = "" # Location of SSLContext's TrustManagers store
#password = "" # Password for SSLContext's TrustManagers store
#algorithm = "" # Algorithm used by SSLContext's TrustManagers store
}
}
ahc {
#keepAlive = true # Allow pooling HTTP connections (keep-alive header automatically added)
#connectTimeout = 60000 # Timeout when establishing a connection
#pooledConnectionIdleTimeout = 60000 # Timeout when a connection stays unused in the pool
#readTimeout = 60000 # Timeout when a used connection stays idle
#maxRetry = 2 # Number of times that a request should be tried again
#requestTimeout = 60000 # Timeout of the requests
#acceptAnyCertificate = true # When set to true, doesn't validate SSL certificates
#httpClientCodecMaxInitialLineLength = 4096 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK")
#httpClientCodecMaxHeaderSize = 8192 # Maximum size, in bytes, of each request's headers
#httpClientCodecMaxChunkSize = 8192 # Maximum length of the content or each chunk
#webSocketMaxFrameSize = 10240000 # Maximum frame payload size
#sslEnabledProtocols = [TLSv1.2, TLSv1.1, TLSv1] # Array of enabled protocols for HTTPS, if empty use the JDK defaults
#sslEnabledCipherSuites = [] # Array of enabled cipher suites for HTTPS, if empty use the JDK defaults
#sslSessionCacheSize = 0 # SSLSession cache size, set to 0 to use JDK's default
#sslSessionTimeout = 0 # SSLSession timeout in seconds, set to 0 to use JDK's default (24h)
#useOpenSsl = false # if OpenSSL should be used instead of JSSE (requires tcnative jar)
#useNativeTransport = false # if native transport should be used instead of Java NIO (requires netty-transport-native-epoll, currently Linux only)
#usePooledMemory = true # if Gatling should use pooled memory
#tcpNoDelay = true
#soReuseAddress = false
#soLinger = -1
#soSndBuf = -1
#soRcvBuf = -1
}
dns {
#queryTimeout = 5000 # Timeout of each DNS query in millis
#maxQueriesPerResolve = 3 # Maximum allowed number of DNS queries for a given name resolution
}
}
data {
#writers = [console, file] # The list of DataWriters to which Gatling write simulation data (currently supported : console, file, graphite, jdbc)
console {
#light = false # When set to true, displays a light version without detailed request stats
}
file {
#bufferSize = 8192 # FileDataWriter's internal data buffer size, in bytes
}
leak {
#noActivityTimeout = 30 # Period, in seconds, for which Gatling may have no activity before considering a leak may be happening
}
graphite {
#light = false # only send the all* stats
#host = "localhost" # The host where the Carbon server is located
#port = 2003 # The port to which the Carbon server listens to (2003 is default for plaintext, 2004 is default for pickle)
#protocol = "tcp" # The protocol used to send data to Carbon (currently supported : "tcp", "udp")
#rootPathPrefix = "gatling" # The common prefix of all metrics sent to Graphite
#bufferSize = 8192 # GraphiteDataWriter's internal data buffer size, in bytes
#writeInterval = 1 # GraphiteDataWriter's write interval, in seconds
}
}
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%-5level] %logger{15} - %msg%n%rEx</pattern>
<immediateFlush>false</immediateFlush>
</encoder>
</appender>
<!-- Uncomment for logging ALL HTTP request and responses -->
<!-- <logger name="io.gatling.http.ahc" level="TRACE" /> -->
<!-- <logger name="io.gatling.http.response" level="TRACE" /> -->
<!-- Uncomment for logging ONLY FAILED HTTP request and responses -->
<!-- <logger name="io.gatling.http.ahc" level="DEBUG" /> -->
<!-- <logger name="io.gatling.http.response" level="DEBUG" /> -->
<root level="WARN">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

View File

@@ -0,0 +1,53 @@
recorder {
core {
#mode = "Proxy"
#encoding = "utf-8" # The encoding used for reading/writing request bodies and the generated simulation
#outputFolder = "" # The folder where generated simulation will we written
#package = "" # The package's name of the generated simulation
#className = "RecordedSimulation" # The name of the generated Simulation class
#thresholdForPauseCreation = 100 # The minimum time, in milliseconds, that must pass between requests to trigger a pause creation
#saveConfig = false # When set to true, the configuration from the Recorder GUI overwrites this configuration
#headless = false # When set to true, run the Recorder in headless mode instead of the GUI
#harFilePath = "" # The path of the HAR file to convert
}
filters {
#filterStrategy = "Disabled" # The selected filter resources filter strategy (currently supported : "Disabled", "BlackList", "WhiteList")
#whitelist = [] # The list of ressources patterns that are part of the Recorder's whitelist
#blacklist = [] # The list of ressources patterns that are part of the Recorder's blacklist
}
http {
#automaticReferer = true # When set to false, write the referer + enable 'disableAutoReferer' in the generated simulation
#followRedirect = true # When set to false, write redirect requests + enable 'disableFollowRedirect' in the generated simulation
#removeCacheHeaders = true # When set to true, removes from the generated requests headers leading to request caching
#inferHtmlResources = true # When set to true, add inferred resources + set 'inferHtmlResources' with the configured blacklist/whitelist in the generated simulation
#checkResponseBodies = false # When set to true, save response bodies as files and add raw checks in the generated simulation
}
proxy {
#port = 8000 # Local port used by Gatling's Proxy for HTTP/HTTPS
https {
#mode = "SelfSignedCertificate" # The selected "HTTPS mode" (currently supported : "SelfSignedCertificate", "ProvidedKeyStore", "GatlingCertificateAuthority", "CustomCertificateAuthority")
keyStore {
#path = "" # The path of the custom key store
#password = "" # The password for this key store
#type = "JKS" # The type of the key store (currently supported: "JKS")
}
certificateAuthority {
#certificatePath = "" # The path of the custom certificate
#privateKeyPath = "" # The certificate's private key path
}
}
outgoing {
#host = "" # The outgoing proxy's hostname
#username = "" # The username to use to connect to the outgoing proxy
#password = "" # The password corresponding to the user to use to connect to the outgoing proxy
#port = 0 # The HTTP port to use to connect to the outgoing proxy
#sslPort = 0 # If set, The HTTPS port to use to connect to the outgoing proxy
}
}
netty {
#maxInitialLineLength = 10000 # Maximum length of the initial line of the response (e.g. "HTTP/1.0 200 OK")
#maxHeaderSize = 20000 # Maximum size, in bytes, of each request's headers
#maxChunkSize = 8192 # Maximum length of the content or each chunk
#maxContentLength = 100000000 # Maximum length of the aggregated content of each response
}
}

View File

@@ -0,0 +1,13 @@
import io.gatling.app.Gatling
import io.gatling.core.config.GatlingPropertiesBuilder
object Engine extends App {
val props = new GatlingPropertiesBuilder
props.dataDirectory(IDEPathHelper.dataDirectory.toString)
props.resultsDirectory(IDEPathHelper.resultsDirectory.toString)
props.bodiesDirectory(IDEPathHelper.bodiesDirectory.toString)
props.binariesDirectory(IDEPathHelper.mavenBinariesDirectory.toString)
Gatling.fromMap(props.build)
}

View File

@@ -0,0 +1,22 @@
import java.nio.file.Path
import io.gatling.commons.util.PathHelper._
object IDEPathHelper {
val gatlingConfUrl: Path = getClass.getClassLoader.getResource("gatling.conf").toURI
val projectRootDir = gatlingConfUrl.ancestor(3)
val mavenSourcesDirectory = projectRootDir / "src" / "test" / "scala"
val mavenResourcesDirectory = projectRootDir / "src" / "test" / "resources"
val mavenTargetDirectory = projectRootDir / "target"
val mavenBinariesDirectory = mavenTargetDirectory / "test-classes"
val dataDirectory = mavenResourcesDirectory / "data"
val bodiesDirectory = mavenResourcesDirectory / "bodies"
val recorderOutputDirectory = mavenSourcesDirectory
val resultsDirectory = mavenTargetDirectory / "gatling"
val recorderConfigFile = mavenResourcesDirectory / "recorder.conf"
}

View File

@@ -0,0 +1,12 @@
import io.gatling.recorder.GatlingRecorder
import io.gatling.recorder.config.RecorderPropertiesBuilder
object Recorder extends App {
val props = new RecorderPropertiesBuilder
props.simulationOutputFolder(IDEPathHelper.recorderOutputDirectory.toString)
props.simulationPackage("org.baeldung")
props.bodiesFolder(IDEPathHelper.bodiesDirectory.toString)
GatlingRecorder.fromMap(props.build, Some(IDEPathHelper.recorderConfigFile))
}

View File

@@ -0,0 +1,45 @@
package org.baeldung
import scala.concurrent.duration._
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._
class RecordedSimulation extends Simulation {
val httpProtocol = http
.baseURL("http://computer-database.gatling.io")
.inferHtmlResources(BlackList(""".*\.css""", """.*\.js""", """.*\.ico"""), WhiteList())
.acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.acceptEncodingHeader("gzip, deflate")
.acceptLanguageHeader("it-IT,it;q=0.8,en-US;q=0.5,en;q=0.3")
.userAgentHeader("Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0")
val scn = scenario("RecordedSimulation")
.exec(http("request_0")
.get("/"))
.pause(5)
.exec(http("request_1")
.get("/computers?f=amstrad"))
.pause(4)
.exec(http("request_2")
.get("/computers/412"))
.pause(2)
.exec(http("request_3")
.get("/"))
.pause(2)
.exec(http("request_4")
.get("/computers?p=1"))
.pause(1)
.exec(http("request_5")
.get("/computers?p=2"))
.pause(2)
.exec(http("request_6")
.get("/computers?p=3"))
setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)
}

View File

@@ -0,0 +1 @@
/report-*.json

View File

@@ -0,0 +1,5 @@
### Relevant articles
- [Introduction to Testing with Spock and Groovy](http://www.baeldung.com/groovy-spock)
- [Difference Between Stub, Mock, and Spy in the Spock Framework](https://www.baeldung.com/spock-stub-mock-spy)
- [Guide to Spock Extensions](https://www.baeldung.com/spock-extensions)

View File

@@ -0,0 +1,56 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.spockframework</groupId>
<artifactId>groovy-spock</artifactId>
<version>1.0-SNAPSHOT</version>
<name>groovy-spock</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>${spock-core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy-all.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>${gmavenplus-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<spock-core.version>1.3-groovy-2.4</spock-core.version>
<groovy-all.version>2.4.7</groovy-all.version>
<gmavenplus-plugin.version>1.5</gmavenplus-plugin.version>
</properties>
</project>

View File

@@ -0,0 +1,7 @@
package mocks;
public interface EventPublisher {
void publish(String addedOfferId);
}

View File

@@ -0,0 +1,5 @@
package mocks;
public class ExternalItemProviderException extends RuntimeException {
}

View File

@@ -0,0 +1,36 @@
package mocks;
import java.util.Objects;
public class Item {
private final String id;
private final String name;
public Item(String id, String name) {
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item item = (Item) o;
return Objects.equals(id, item.id) &&
Objects.equals(name, item.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}

View File

@@ -0,0 +1,9 @@
package mocks;
import java.util.List;
public interface ItemProvider {
List<Item> getItems(List<String> itemIds);
}

View File

@@ -0,0 +1,37 @@
package mocks;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class ItemService {
private final ItemProvider itemProvider;
private final EventPublisher eventPublisher;
public ItemService(ItemProvider itemProvider, EventPublisher eventPublisher) {
this.itemProvider = itemProvider;
this.eventPublisher = eventPublisher;
}
List<Item> getAllItemsSortedByName(List<String> itemIds) {
List<Item> items;
try{
items = itemProvider.getItems(itemIds);
} catch (RuntimeException ex) {
throw new ExternalItemProviderException();
}
return items.stream()
.sorted(Comparator.comparing(Item::getName))
.collect(Collectors.toList());
}
void saveItems(List<String> itemIds) {
List<String> notEmptyOfferIds = itemIds.stream()
.filter(itemId -> !itemId.isEmpty())
.collect(Collectors.toList());
// save in database
notEmptyOfferIds.forEach(eventPublisher::publish);
}
}

View File

@@ -0,0 +1,10 @@
package mocks;
public class LoggingEventPublisher implements EventPublisher {
@Override
public void publish(String addedOfferId) {
System.out.println("I've published: " + addedOfferId);
}
}

View File

@@ -0,0 +1,89 @@
import spock.lang.Specification
class FirstSpecification extends Specification {
def "one plus one should equal two"() {
expect:
1 + 1 == 2
}
def "two plus two should equal four"() {
given:
int left = 2
int right = 2
when:
int result = left + right
then:
result == 4
}
def "Should be able to remove from list"() {
given:
def list = [1, 2, 3, 4]
when:
list.remove(0)
then:
list == [2, 3, 4]
}
def "Should get an index out of bounds when removing a non-existent item"() {
given:
def list = [1, 2, 3, 4]
when:
list.remove(20)
then:
thrown(IndexOutOfBoundsException)
list.size() == 4
}
def "numbers to the power of two"(int a, int b, int c) {
expect:
Math.pow(a, b) == c
where:
a | b | c
1 | 2 | 1
2 | 2 | 4
3 | 2 | 9
}
def "Should return default value for mock"() {
given:
def paymentGateway = Mock(PaymentGateway)
when:
def result = paymentGateway.makePayment(12.99)
then:
!result
}
def "Should return true value for mock"() {
given:
def paymentGateway = Mock(PaymentGateway)
paymentGateway.makePayment(20) >> true
when:
def result = paymentGateway.makePayment(20)
then:
result
}
def "Should verify notify was called"() {
given:
def notifier = Mock(Notifier)
when:
notifier.notify('foo')
then:
1 * notifier.notify('foo')
}
}

View File

@@ -0,0 +1,3 @@
interface Notifier {
void notify(String message)
}

View File

@@ -0,0 +1,3 @@
interface PaymentGateway {
boolean makePayment(BigDecimal amount)
}

View File

@@ -0,0 +1,20 @@
package extensions
import spock.lang.Narrative
import spock.lang.Specification
import spock.lang.Title
@Title("""This title is easy to read for humans""")
class CustomTitleTest extends Specification {
}
@Narrative("""
as a user
i want to save favourite items
and then get the list of them
""")
class NarrativeDescriptionTest extends Specification {
}

View File

@@ -0,0 +1,22 @@
package extensions
import spock.lang.IgnoreIf
import spock.lang.Specification
class IgnoreIfTest extends Specification {
@IgnoreIf({System.getProperty("os.name").contains("windows")})
def "I won't run on windows"() {
expect:
true
}
@IgnoreIf({ os.isWindows() })
def "I'm using Spock helper classes to run only on windows"() {
expect:
true
}
}

View File

@@ -0,0 +1,16 @@
package extensions
import spock.lang.IgnoreRest
import spock.lang.Specification
class IgnoreRestTest extends Specification {
def "I won't run"() { }
@IgnoreRest
def 'I will run'() { }
def "I won't run too"() { }
}

View File

@@ -0,0 +1,20 @@
package extensions
import spock.lang.Ignore
import spock.lang.Specification
@Ignore
class IgnoreTest extends Specification {
@Ignore
def "I won't be executed"() {
expect:
true
}
def 'Example test'() {
expect:
true
}
}

View File

@@ -0,0 +1,25 @@
package extensions
import spock.lang.Issue
import spock.lang.Specification
class IssueTest extends Specification {
@Issue("http://jira.org/issues/LO-531")
def 'single issue'() {
}
@Issue(["http://jira.org/issues/LO-531", "http://jira.org/issues/LO-123"])
def 'multiple issues'() {
}
@Issue("LO-1000")
def "I'm using Spock configuration file"() {
expect:
true
}
}

View File

@@ -0,0 +1,11 @@
package extensions
import spock.lang.PendingFeature
class PendingFeatureTest {
@PendingFeature
def 'test for not implemented yet feature'() {
}
}

View File

@@ -0,0 +1,14 @@
package extensions
import spock.lang.Requires
import spock.lang.Specification
class RequiresTest extends Specification {
@Requires({ System.getProperty("os.name").contains("windows") })
def "I will run only on Windows"() {
expect:
true
}
}

View File

@@ -0,0 +1,18 @@
package extensions
import spock.lang.Specification
import spock.util.environment.RestoreSystemProperties
class RestoreSystemPropertiesTest extends Specification {
@RestoreSystemProperties
def 'all environment variables will be saved before execution and restored after tests'() {
given:
System.setProperty('os.name', 'Mac OS')
expect:
true
}
}

View File

@@ -0,0 +1,20 @@
package extensions
import spock.lang.Retry
import spock.lang.Specification
@Retry
class RetryTest extends Specification {
@Retry
def 'I will retry three times'() { }
@Retry(exceptions = [RuntimeException])
def 'I will retry only on RuntimeException'() { }
@Retry(condition = { failure.message.contains('error') })
def 'I will retry with a specific message'() { }
@Retry(delay = 1000)
def 'I will retry after 1000 millis'() { }
}

View File

@@ -0,0 +1,20 @@
package extensions
import spock.lang.See
import spock.lang.Specification
class SeeTest extends Specification {
@See("https://example.org")
def 'Look at the reference'() {
}
@See(["https://example.org/first", "https://example.org/first"])
def 'Look at the references'() {
}
}

View File

@@ -0,0 +1,13 @@
package extensions
import org.junit.Ignore
import spock.lang.Specification
class StackTraceTest extends Specification {
def 'stkacktrace'() {
// expect:
// throw new RuntimeException("blabla")
}
}

View File

@@ -0,0 +1,14 @@
package extensions
import spock.lang.Specification
import spock.lang.Stepwise
@Stepwise
class StepwiseTest extends Specification {
def 'I will run as first'() { }
def 'I will run as second'() { }
}

View File

@@ -0,0 +1,13 @@
package extensions
import mocks.ItemService
import spock.lang.Specification
import spock.lang.Subject
class SubjectTest extends Specification {
@Subject
ItemService itemService // initialization here...
}

View File

@@ -0,0 +1,24 @@
package extensions
import spock.lang.Specification
import spock.lang.Timeout
import java.util.concurrent.TimeUnit
@Timeout(5)
class TimeoutTest extends Specification {
@Timeout(1)
def 'I have one second to finish'() {
}
def 'I will have 5 seconds timeout'() {}
@Timeout(value = 200, unit = TimeUnit.SECONDS)
def 'I will fail after 200 millis'() {
expect:
true
}
}

View File

@@ -0,0 +1,131 @@
package mocks
import spock.lang.Specification
class ItemServiceUnitTest extends Specification {
ItemProvider itemProvider
ItemService itemService
EventPublisher eventPublisher
def setup() {
itemProvider = Stub(ItemProvider)
eventPublisher = Mock(EventPublisher)
itemService = new ItemService(itemProvider, eventPublisher)
}
def 'should return items sorted by name'() {
given:
def ids = ['offer-id', 'offer-id-2']
itemProvider.getItems(ids) >> [new Item('offer-id-2', 'Zname'), new Item('offer-id', 'Aname')]
when:
List<Item> items = itemService.getAllItemsSortedByName(ids)
then:
items.collect { it.name } == ['Aname', 'Zname']
}
def 'arguments constraints'() {
itemProvider.getItems(['offer-id'])
itemProvider.getItems(_) >> []
itemProvider.getItems(*_) >> []
itemProvider.getItems(!null) >> []
itemProvider.getItems({ it.size > 0 }) >> []
}
def 'should return different items on subsequent call'() {
given:
itemProvider.getItems(_) >>> [
[],
[new Item('1', 'name')],
[new Item('2', 'name')]
]
when: 'method is called for the first time'
List<Item> items = itemService.getAllItemsSortedByName(['not-important'])
then: 'empty list is returned'
items == []
when: 'method is called for the second time'
items = itemService.getAllItemsSortedByName(['not-important'])
then: 'item with id=1 is returned'
items == [new Item('1', 'name')]
when: 'method is called for the thirdtime'
items = itemService.getAllItemsSortedByName(['not-important'])
then: 'item with id=2 is returned'
items == [new Item('2', 'name')]
}
def 'should throw ExternalItemProviderException when ItemProvider fails'() {
given:
itemProvider.getItems(_) >> { new RuntimeException()}
when:
itemService.getAllItemsSortedByName([])
then:
thrown(ExternalItemProviderException)
}
def 'chaining response'() {
itemProvider.getItems(_) >>> { new RuntimeException() } >> new SocketTimeoutException() >> [new Item('id', 'name')]
}
def 'should return different items for different ids lists'() {
given:
def firstIds = ['first']
def secondIds = ['second']
itemProvider.getItems(firstIds) >> [new Item('first', 'Zname')]
itemProvider.getItems(secondIds) >> [new Item('second', 'Aname')]
when:
def firstItems = itemService.getAllItemsSortedByName(firstIds)
def secondItems = itemService.getAllItemsSortedByName(secondIds)
then:
firstItems.first().name == 'Zname'
secondItems.first().name == 'Aname'
}
def 'should publish events about new non-empty saved offers'() {
given:
def offerIds = ['', 'a', 'b']
when:
itemService.saveItems(offerIds)
then:
2 * eventPublisher.publish({ it != null && !it.isEmpty()})
}
def 'should return items'() {
given:
itemProvider = Mock(ItemProvider)
itemProvider.getItems(['item-id']) >> [new Item('item-id', 'name')]
itemService = new ItemService(itemProvider, eventPublisher)
when:
def items = itemService.getAllItemsSortedByName(['item-id'])
then:
items == [new Item('item-id', 'name')]
}
def 'should spy on EventPublisher method call'() {
given:
LoggingEventPublisher eventPublisher = Spy(LoggingEventPublisher)
itemService = new ItemService(itemProvider, eventPublisher)
when:
itemService.saveItems(['item-id'])
then:
1 * eventPublisher.publish('item-id')
}
}

View File

@@ -0,0 +1,30 @@
import extensions.TimeoutTest
import spock.lang.Issue
runner {
if (System.getenv("FILTER_STACKTRACE") == null) {
filterStackTrace false
}
report {
issueNamePrefix 'Bug '
issueUrlPrefix 'http://jira.org/issues/'
}
optimizeRunOrder true
// exclude TimeoutTest
// exclude {
// baseClass TimeoutTest
// annotation Issue
// }
report {
enabled true
logFileDir '.'
logFileName 'report.json'
logFileSuffix new Date().format('yyyy-MM-dd')
}
}

View File

@@ -0,0 +1,3 @@
### Relevant Articles
- [Guide to JUnit 4 Rules](https://www.baeldung.com/junit-4-rules)

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>junit-4</artifactId>
<version>1.0-SNAPSHOT</version>
<name>junit-4</name>
<description>JUnit 4 Topics</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>
<version>${jUnitParams.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<jUnitParams.version>1.1.0</jUnitParams.version>
</properties>
</project>

View File

@@ -0,0 +1,15 @@
package com.baeldung.junitparams;
public class SafeAdditionUtil {
public int safeAdd(int a, int b) {
long result = ((long) a) + b;
if (result > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
} else if (result < Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
return (int) result;
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,54 @@
package com.baeldung.junitparams;
import junitparams.FileParameters;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
@RunWith(JUnitParamsRunner.class)
public class SafeAdditionUtilUnitTest {
private SafeAdditionUtil serviceUnderTest = new SafeAdditionUtil();
@Test
@Parameters({"1, 2, 3", "-10, 30, 20", "15, -5, 10", "-5, -10, -15"})
public void whenWithAnnotationProvidedParams_thenSafeAdd(int a, int b, int expectedValue) {
assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}
@Test
@Parameters(method = "parametersToTestAdd")
public void whenWithNamedMethod_thendSafeAdd(int a, int b, int expectedValue) {
assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}
private Object[] parametersToTestAdd() {
return new Object[]{new Object[]{1, 2, 3}, new Object[]{-10, 30, 20}, new Object[]{Integer.MAX_VALUE, 2, Integer.MAX_VALUE}, new Object[]{Integer.MIN_VALUE, -8, Integer.MIN_VALUE}};
}
@Test
@Parameters
public void whenWithnoParam_thenLoadByNameSafeAdd(int a, int b, int expectedValue) {
assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}
private Object[] parametersForWhenWithnoParam_thenLoadByNameSafeAdd() {
return new Object[]{new Object[]{1, 2, 3}, new Object[]{-10, 30, 20}, new Object[]{Integer.MAX_VALUE, 2, Integer.MAX_VALUE}, new Object[]{Integer.MIN_VALUE, -8, Integer.MIN_VALUE}};
}
@Test
@Parameters(source = TestDataProvider.class)
public void whenWithNamedClass_thenSafeAdd(int a, int b, int expectedValue) {
assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}
@Test
@FileParameters("src/test/resources/JunitParamsTestParameters.csv")
public void whenWithCsvFile_thenSafeAdd(int a, int b, int expectedValue) {
assertEquals(expectedValue, serviceUnderTest.safeAdd(a, b));
}
}

View File

@@ -0,0 +1,13 @@
package com.baeldung.junitparams;
public class TestDataProvider {
public static Object[] provideBasicData() {
return new Object[]{new Object[]{1, 2, 3}, new Object[]{-10, 30, 20}, new Object[]{15, -5, 10}, new Object[]{-5, -10, -15}};
}
public static Object[] provideEdgeCaseData() {
return new Object[]{new Object[]{Integer.MAX_VALUE, 2, Integer.MAX_VALUE}, new Object[]{Integer.MIN_VALUE, -2, Integer.MIN_VALUE},};
}
}

View File

@@ -0,0 +1,34 @@
package com.baeldung.rules;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MessageLogger implements TestRule {
private static final Logger LOG = LoggerFactory.getLogger(MessageLogger.class);
private String message;
public MessageLogger(String message) {
this.message = message;
}
@Override
public Statement apply(final Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
LOG.info("Starting: {}", message);
base.evaluate();
} finally {
LOG.info("Finished: {}", message);
}
}
};
}
}

View File

@@ -0,0 +1,21 @@
package com.baeldung.rules;
import static org.junit.Assert.assertTrue;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
public class RuleChainUnitTest {
@Rule
public RuleChain chain = RuleChain.outerRule(new MessageLogger("First rule"))
.around(new MessageLogger("Second rule"))
.around(new MessageLogger("Third rule"));
@Test
public void givenRuleChain_whenTestRuns_thenChainOrderApplied() {
assertTrue(true);
}
}

View File

@@ -0,0 +1,88 @@
package com.baeldung.rules;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.isA;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.ErrorCollector;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestName;
import org.junit.rules.Timeout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RulesUnitTest {
private static final Logger LOG = LoggerFactory.getLogger(RulesUnitTest.class);
@Rule
public TemporaryFolder tmpFolder = new TemporaryFolder();
@Rule
public final ExpectedException thrown = ExpectedException.none();
@Rule
public TestName name = new TestName();
@Rule
public Timeout globalTimeout = Timeout.seconds(10);
@Rule
public final ErrorCollector errorCollector = new ErrorCollector();
@Rule
public DisableOnDebug disableTimeout = new DisableOnDebug(Timeout.seconds(30));
@Rule
public TestMethodNameLogger testLogger = new TestMethodNameLogger();
@Test
public void givenTempFolderRule_whenNewFile_thenFileIsCreated() throws IOException {
File testFile = tmpFolder.newFile("test-file.txt");
assertTrue("The file should have been created: ", testFile.isFile());
assertEquals("Temp folder and test file should match: ", tmpFolder.getRoot(), testFile.getParentFile());
}
@Test
public void givenIllegalArgument_whenExceptionThrown_thenMessageAndCauseMatches() {
thrown.expect(IllegalArgumentException.class);
thrown.expectCause(isA(NullPointerException.class));
thrown.expectMessage("This is illegal");
throw new IllegalArgumentException("This is illegal", new NullPointerException());
}
@Test
public void givenAddition_whenPrintingTestName_thenTestNameIsDisplayed() {
LOG.info("Executing: {}", name.getMethodName());
assertEquals("givenAddition_whenPrintingTestName_thenTestNameIsDisplayed", name.getMethodName());
}
@Ignore
@Test
public void givenLongRunningTest_whenTimout_thenTestFails() throws InterruptedException {
TimeUnit.SECONDS.sleep(20);
}
@Ignore
@Test
public void givenMultipleErrors_whenTestRuns_thenCollectorReportsErrors() {
errorCollector.addError(new Throwable("First thing went wrong!"));
errorCollector.addError(new Throwable("Another thing went wrong!"));
errorCollector.checkThat("Hello World", not(containsString("ERROR!")));
}
}

View File

@@ -0,0 +1,32 @@
package com.baeldung.rules;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestMethodNameLogger implements TestRule {
private static final Logger LOG = LoggerFactory.getLogger(TestMethodNameLogger.class);
@Override
public Statement apply(Statement base, Description description) {
logInfo("Before test", description);
try {
return new Statement() {
@Override
public void evaluate() throws Throwable {
base.evaluate();
}
};
} finally {
logInfo("After test", description);
}
}
private void logInfo(String msg, Description description) {
LOG.info(msg + description.getMethodName());
}
}

View File

@@ -0,0 +1,30 @@
package com.baeldung.rules;
import static org.junit.Assert.assertFalse;
import java.util.ArrayList;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Verifier;
public class VerifierRuleUnitTest {
private List<String> messageLog = new ArrayList<String>();
@Rule
public Verifier verifier = new Verifier() {
@Override
public void verify() {
assertFalse("Message Log is not Empty!", messageLog.isEmpty());
}
};
@Test
public void givenNewMessage_whenVerified_thenMessageLogNotEmpty() {
// ...
messageLog.add("There is a new message!");
}
}

View File

@@ -0,0 +1,24 @@
package com.baeldung.runfromjava;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class FirstUnitTest {
@Test
public void whenThis_thenThat() {
assertTrue(true);
}
@Test
public void whenSomething_thenSomething() {
assertTrue(true);
}
@Test
public void whenSomethingElse_thenSomethingElse() {
assertTrue(true);
}
}

View File

@@ -0,0 +1,10 @@
package com.baeldung.runfromjava;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({ FirstUnitTest.class, SecondUnitTest.class })
public class MyTestSuite {
}

View File

@@ -0,0 +1,93 @@
package com.baeldung.runfromjava;
import junit.extensions.ActiveTestSuite;
import junit.extensions.RepeatedTest;
import junit.framework.JUnit4TestAdapter;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.junit.internal.TextListener;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
public class RunJUnit4TestsFromJava {
public static void runOne() {
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
junit.run(FirstUnitTest.class);
}
public static void runAllClasses() {
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
Result result = junit.run(FirstUnitTest.class, SecondUnitTest.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
resultReport(result);
}
public static void runSuiteOfClasses() {
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
Result result = junit.run(MyTestSuite.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
resultReport(result);
}
public static void runRepeated() {
Test test = new JUnit4TestAdapter(SecondUnitTest.class);
RepeatedTest repeatedTest = new RepeatedTest(test, 5);
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
junit.run(repeatedTest);
}
public static void runRepeatedSuite() {
TestSuite mySuite = new ActiveTestSuite();
JUnitCore junit = new JUnitCore();
junit.addListener(new TextListener(System.out));
mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(FirstUnitTest.class), 5));
mySuite.addTest(new RepeatedTest(new JUnit4TestAdapter(SecondUnitTest.class), 3));
junit.run(mySuite);
}
public static void resultReport(Result result) {
System.out.println("Finished. Result: Failures: " +
result.getFailureCount() + ". Ignored: " +
result.getIgnoreCount() + ". Tests run: " +
result.getRunCount() + ". Time: " +
result.getRunTime() + "ms.");
}
public static void main(String[] args) {
System.out.println("\nRunning one test class:");
runOne();
System.out.println("\nRunning all test classes:");
runAllClasses();
System.out.println("\nRunning a suite of test classes:");
runSuiteOfClasses();
System.out.println("\nRunning repeated tests:");
runRepeated();
System.out.println("\nRunning repeated suite tests:");
runRepeatedSuite();
}
}

View File

@@ -0,0 +1,18 @@
package com.baeldung.runfromjava;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class SecondUnitTest {
@Test
public void whenSomething_thenSomething() {
assertTrue(true);
}
@Test
public void whensomethingElse_thenSomethingElse() {
assertTrue(true);
}
}

View File

@@ -0,0 +1,4 @@
1,2,3
-10, 30, 20
15, -5, 10
-5, -10, -15
1 1 2 3
2 -10 30 20
3 15 -5 10
4 -5 -10 -15

View File

@@ -0,0 +1,4 @@
## Relevant Articles:
- [JUnit 5 TestWatcher API](https://www.baeldung.com/junit-testwatcher)
- [JUnit Custom Display Name Generator API](https://www.baeldung.com/junit-custom-display-name-generator)

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>junit-5-advanced</artifactId>
<version>1.0-SNAPSHOT</version>
<name>junit-5-advanced</name>
<description>Advanced JUnit 5 Topics</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter.version}</version>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.vintage.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
</plugin>
</plugins>
</build>
<properties>
<junit-jupiter.version>5.4.2</junit-jupiter.version>
<maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version>
<junit.vintage.version>5.4.2</junit.vintage.version>
</properties>
</project>

View File

@@ -0,0 +1,15 @@
package com.baeldung.failure_vs_error;
/**
* @author paullatzelsperger
* @since 2019-07-17
*/
public class SimpleCalculator {
public static double divideNumbers(double dividend, double divisor) {
if (divisor == 0) {
throw new ArithmeticException("Division by zero!");
}
return dividend / divisor;
}
}

View File

@@ -0,0 +1,27 @@
package com.baeldung.junit5.testinstance;
import java.io.Serializable;
public class Tweet implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
private String content;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}

View File

@@ -0,0 +1,10 @@
package com.baeldung.junit5.testinstance;
public class TweetException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TweetException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,41 @@
package com.baeldung.junit5.testinstance;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class TweetSerializer {
private static final int MAX_TWEET_SIZE = 1000;
private static final int MIN_TWEET_SIZE = 150;
private final Tweet tweet;
public TweetSerializer(Tweet tweet) {
this.tweet = tweet;
}
public byte[] serialize() throws IOException {
byte[] tweetContent = serializeTweet();
int totalLength = tweetContent.length;
validateSizeOfTweet(totalLength);
return tweetContent;
}
private void validateSizeOfTweet(int tweetSize) {
if (tweetSize > MAX_TWEET_SIZE) {
throw new TweetException("Tweet is too large");
}
if (tweetSize < MIN_TWEET_SIZE) {
throw new TweetException("Tweet is too small");
}
}
private byte[] serializeTweet() throws IOException {
try (ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectStream = new ObjectOutputStream(arrayOutputStream)) {
objectStream.writeObject(tweet);
return arrayOutputStream.toByteArray();
}
}
}

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@@ -0,0 +1,87 @@
package com.baeldung.displayname;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import java.lang.reflect.Method;
@DisplayNameGeneration(DisplayNameGeneratorUnitTest.ReplaceCamelCase.class)
class DisplayNameGeneratorUnitTest {
@Test
void camelCaseName() {
}
@Nested
@DisplayNameGeneration(DisplayNameGeneratorUnitTest.IndicativeSentences.class)
class ANumberIsFizz {
@Test
void ifItIsDivisibleByThree() {
}
@ParameterizedTest(name = "Number {0} is fizz.")
@ValueSource(ints = { 3, 12, 18 })
void ifItIsOneOfTheFollowingNumbers(int number) {
}
}
@Nested
@DisplayNameGeneration(DisplayNameGeneratorUnitTest.IndicativeSentences.class)
class ANumberIsBuzz {
@Test
void ifItIsDivisibleByFive() {
}
@ParameterizedTest(name = "Number {0} is buzz.")
@ValueSource(ints = { 5, 10, 20 })
void ifItIsOneOfTheFollowingNumbers(int number) {
}
}
static class IndicativeSentences extends ReplaceCamelCase {
@Override
public String generateDisplayNameForNestedClass(Class<?> nestedClass) {
return super.generateDisplayNameForNestedClass(nestedClass) + "...";
}
@Override
public String generateDisplayNameForMethod(Class<?> testClass, Method testMethod) {
return replaceCamelCase(testClass.getSimpleName() + " " + testMethod.getName()) + ".";
}
}
static class ReplaceCamelCase extends DisplayNameGenerator.Standard {
@Override
public String generateDisplayNameForClass(Class<?> testClass) {
return replaceCamelCase(super.generateDisplayNameForClass(testClass));
}
@Override
public String generateDisplayNameForNestedClass(Class<?> nestedClass) {
return replaceCamelCase(super.generateDisplayNameForNestedClass(nestedClass));
}
@Override
public String generateDisplayNameForMethod(Class<?> testClass, Method testMethod) {
return this.replaceCamelCase(testMethod.getName()) + DisplayNameGenerator.parameterTypesAsString(testMethod);
}
String replaceCamelCase(String camelCase) {
StringBuilder result = new StringBuilder();
result.append(camelCase.charAt(0));
for (int i=1; i<camelCase.length(); i++) {
if (Character.isUpperCase(camelCase.charAt(i))) {
result.append(' ');
result.append(Character.toLowerCase(camelCase.charAt(i)));
} else {
result.append(camelCase.charAt(i));
}
}
return result.toString();
}
}
}

View File

@@ -0,0 +1,20 @@
package com.baeldung.displayname;
import org.junit.jupiter.api.*;
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
class ReplaceUnderscoresGeneratorUnitTest {
@Nested
class when_doing_something {
@Test
void then_something_should_happen() {
}
@Test
@DisplayName("@DisplayName takes precedence over generation")
void override_generator() {
}
}
}

View File

@@ -0,0 +1,62 @@
package com.baeldung.extensions.testwatcher;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.TestWatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestResultLoggerExtension implements TestWatcher, AfterAllCallback {
private static final Logger LOG = LoggerFactory.getLogger(TestResultLoggerExtension.class);
private List<TestResultStatus> testResultsStatus = new ArrayList<>();
private enum TestResultStatus {
SUCCESSFUL, ABORTED, FAILED, DISABLED;
}
@Override
public void testDisabled(ExtensionContext context, Optional<String> reason) {
LOG.info("Test Disabled for test {}: with reason :- {}", context.getDisplayName(), reason.orElse("No reason"));
testResultsStatus.add(TestResultStatus.DISABLED);
}
@Override
public void testSuccessful(ExtensionContext context) {
LOG.info("Test Successful for test {}: ", context.getDisplayName());
testResultsStatus.add(TestResultStatus.SUCCESSFUL);
}
@Override
public void testAborted(ExtensionContext context, Throwable cause) {
LOG.info("Test Aborted for test {}: ", context.getDisplayName());
testResultsStatus.add(TestResultStatus.ABORTED);
}
@Override
public void testFailed(ExtensionContext context, Throwable cause) {
LOG.info("Test Aborted for test {}: ", context.getDisplayName());
testResultsStatus.add(TestResultStatus.FAILED);
}
@Override
public void afterAll(ExtensionContext context) throws Exception {
Map<TestResultStatus, Long> summary = testResultsStatus.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
LOG.info("Test result summary for {} {}", context.getDisplayName(), summary.toString());
}
}

View File

@@ -0,0 +1,36 @@
package com.baeldung.extensions.testwatcher;
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.Assert;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(TestResultLoggerExtension.class)
class TestWatcherAPIUnitTest {
@Test
void givenFalseIsTrue_whenTestAbortedThenCaptureResult() {
Assumptions.assumeTrue(false);
}
@Disabled
@Test
void givenTrueIsTrue_whenTestDisabledThenCaptureResult() {
Assert.assertTrue(true);
}
@Test
void givenTrueIsTrue_whenTestAbortedThenCaptureResult() {
Assumptions.assumeTrue(true);
}
@Disabled("This test is disabled")
@Test
void givenFailure_whenTestDisabledWithReason_ThenCaptureResult() {
fail("Not yet implemented");
}
}

View File

@@ -0,0 +1,32 @@
package com.baeldung.failure_vs_error;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author paullatzelsperger
* @since 2019-07-17
*/
class SimpleCalculatorUnitTest {
@Test
void divideNumbers() {
double result = SimpleCalculator.divideNumbers(6, 3);
assertEquals(2, result);
}
@Test
@Disabled("test is expected to fail, disabled so that CI build still goes through")
void divideNumbers_failure() {
double result = SimpleCalculator.divideNumbers(6, 3);
assertEquals(15, result);
}
@Test
@Disabled("test is expected to raise an error, disabled so that CI build still goes through")
void divideNumbers_error() {
SimpleCalculator.divideNumbers(10, 0);
}
}

View File

@@ -0,0 +1,22 @@
package com.baeldung.junit5.testinstance;
import static org.junit.Assert.assertEquals;
import org.junit.jupiter.api.Test;
class AdditionUnitTest {
private int sum = 1;
@Test
void addingTwoToSumReturnsThree() {
sum += 2;
assertEquals(3, sum);
}
@Test
void addingThreeToSumReturnsFour() {
sum += 3;
assertEquals(4, sum);
}
}

View File

@@ -0,0 +1,38 @@
package com.baeldung.junit5.testinstance;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(OrderAnnotation.class)
@TestInstance(Lifecycle.PER_CLASS)
class OrderUnitTest {
private int sum;
@BeforeAll
void init() {
sum = 1;
}
@Test
@Order(1)
void firstTest() {
sum += 2;
assertEquals(3, sum);
}
@Test
@Order(2)
void secondTest() {
sum += 3;
assertEquals(6, sum);
}
}

View File

@@ -0,0 +1,62 @@
package com.baeldung.junit5.testinstance;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class TweetSerializerJUnit4UnitTest {
private static String largeContent;
private static String content;
private static String smallContent;
private static Tweet tweet;
@Rule
public ExpectedException expectedException = ExpectedException.none();
@BeforeClass
public static void setUpFixture() throws IOException {
content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
smallContent = "Lorem ipsum dolor";
largeContent = new String(Files.readAllBytes(Paths.get("src/test/resources/lorem-ipsum.txt")));
tweet = new Tweet();
tweet.setId("AX1346");
}
@Test
public void serializerThrowsExceptionWhenMessageIsTooLarge() throws IOException {
tweet.setContent(largeContent);
expectedException.expect(TweetException.class);
expectedException.expectMessage("Tweet is too large");
new TweetSerializer(tweet).serialize();
}
@Test
public void serializerThrowsExceptionWhenMessageIsTooSmall() throws IOException {
tweet.setContent(smallContent);
expectedException.expect(TweetException.class);
expectedException.expectMessage("Tweet is too small");
new TweetSerializer(tweet).serialize();
}
@Test
public void serializeTweet() throws IOException {
tweet.setContent(content);
byte[] content = new TweetSerializer(tweet).serialize();
assertThat(content, is(notNullValue()));
}
}

View File

@@ -0,0 +1,59 @@
package com.baeldung.junit5.testinstance;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
@TestInstance(Lifecycle.PER_CLASS)
class TweetSerializerUnitTest {
private String largeContent;
private String content;
private String smallContent;
private Tweet tweet;
@BeforeAll
void setUpFixture() throws IOException {
content = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
smallContent = "Lorem ipsum dolor";
largeContent = new String(Files.readAllBytes(Paths.get("src/test/resources/lorem-ipsum.txt")));
tweet = new Tweet();
tweet.setId("AX1346");
}
@Test
void serializerThrowsExceptionWhenMessageIsTooLarge() throws IOException {
tweet.setContent(largeContent);
TweetException tweetException = assertThrows(TweetException.class, () -> new TweetSerializer(tweet).serialize());
assertThat(tweetException.getMessage(), is(equalTo("Tweet is too large")));
}
@Test
void serializerThrowsExceptionWhenMessageIsTooSmall() throws IOException {
tweet.setContent(smallContent);
TweetException tweetException = assertThrows(TweetException.class, () -> new TweetSerializer(tweet).serialize());
assertThat(tweetException.getMessage(), is(equalTo("Tweet is too small")));
}
@Test
void serializeTweet() throws IOException {
tweet.setContent(content);
byte[] content = new TweetSerializer(tweet).serialize();
assertThat(content, is(notNullValue()));
}
}

View File

@@ -0,0 +1,4 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View File

@@ -0,0 +1,11 @@
### Relevant Articles:
- [A Guide to JUnit 5](http://www.baeldung.com/junit-5)
- [JUnit5 @RunWith](http://www.baeldung.com/junit-5-runwith)
- [Get the Path of the /src/test/resources Directory in JUnit](https://www.baeldung.com/junit-src-test-resources-directory-path)
- [Tagging and Filtering JUnit Tests](https://www.baeldung.com/junit-filtering-tests)
- [JUnit 5 Temporary Directory Support](https://www.baeldung.com/junit-5-temporary-directory)
- [@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll](http://www.baeldung.com/junit-before-beforeclass-beforeeach-beforeall)
- [JUnit 5 @Test Annotation](http://www.baeldung.com/junit-5-test-annotation)
- [Migrating from JUnit 4 to JUnit 5](http://www.baeldung.com/junit-5-migration)
- [Assert an Exception is Thrown in JUnit 4 and 5](http://www.baeldung.com/junit-assert-exception)
- [The Difference Between Failure and Error in JUnit](https://www.baeldung.com/junit-failure-vs-error)

View File

@@ -0,0 +1,160 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>junit-5-basics</artifactId>
<version>1.0-SNAPSHOT</version>
<name>junit-5-basics</name>
<description>Intro to JUnit 5</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit-platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
<version>${junit.vintage.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-migrationsupport</artifactId>
<version>${junit.vintage.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>filtering</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<excludes>
**/*IntegrationTest.java
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>category</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<groups>com.baeldung.categories.UnitTest</groups>
<excludedGroups>com.baeldung.categories.IntegrationTest</excludedGroups>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>tags</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<groups>UnitTest</groups>
<excludedGroups>IntegrationTest</excludedGroups>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<junit.vintage.version>5.4.2</junit.vintage.version>
<junit-platform.version>1.2.0</junit-platform.version>
<junit-jupiter.version>5.4.2</junit-jupiter.version>
<spring.version>5.0.6.RELEASE</spring.version>
<maven-surefire-plugin.version>2.21.0</maven-surefire-plugin.version>
</properties>
</project>

View File

@@ -0,0 +1,15 @@
package com.baeldung.failure_vs_error;
/**
* @author paullatzelsperger
* @since 2019-07-17
*/
public class SimpleCalculator {
public static double divideNumbers(double dividend, double divisor) {
if (divisor == 0) {
throw new ArithmeticException("Division by zero!");
}
return dividend / divisor;
}
}

View File

@@ -0,0 +1,44 @@
package com.baeldung.junit.tags.example;
public class Employee {
private int id;
private String firstName;
private String lastName;
private String address;
public int getId() {
return id;
}
public void setId(final int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
public String getAddress() {
return address;
}
public void setAddress(final String address) {
this.address = address;
}
}

View File

@@ -0,0 +1,58 @@
package com.baeldung.junit.tags.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Repository
public class EmployeeDAO {
private JdbcTemplate jdbcTemplate;
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
private SimpleJdbcInsert simpleJdbcInsert;
@Autowired
public void setDataSource(final DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
simpleJdbcInsert = new SimpleJdbcInsert(dataSource).withTableName("EMPLOYEE");
}
public int getCountOfEmployees() {
return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM EMPLOYEE", Integer.class);
}
public List<Employee> getAllEmployees() {
return jdbcTemplate.query("SELECT * FROM EMPLOYEE", new EmployeeRowMapper());
}
public int addEmplyee(final int id) {
return jdbcTemplate.update("INSERT INTO EMPLOYEE VALUES (?, ?, ?, ?)", id, "Bill", "Gates", "USA");
}
public int addEmplyeeUsingSimpelJdbcInsert(final Employee emp) {
final Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("ID", emp.getId());
parameters.put("FIRST_NAME", emp.getFirstName());
parameters.put("LAST_NAME", emp.getLastName());
parameters.put("ADDRESS", emp.getAddress());
return simpleJdbcInsert.execute(parameters);
}
// for testing
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}

View File

@@ -0,0 +1,21 @@
package com.baeldung.junit.tags.example;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
public class EmployeeRowMapper implements RowMapper<Employee> {
@Override
public Employee mapRow(final ResultSet rs, final int rowNum) throws SQLException {
final Employee employee = new Employee();
employee.setId(rs.getInt("ID"));
employee.setFirstName(rs.getString("FIRST_NAME"));
employee.setLastName(rs.getString("LAST_NAME"));
employee.setAddress(rs.getString("ADDRESS"));
return employee;
}
}

View File

@@ -0,0 +1,19 @@
package com.baeldung.junit.tags.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
@Configuration
@ComponentScan("com.baeldung.junit.tags.example")
public class SpringJdbcConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("classpath:jdbc/schema.sql").addScript("classpath:jdbc/test-data.sql").build();
}
}

View File

@@ -0,0 +1,9 @@
package com.baeldung.junit5;
public class Greetings {
public static String sayHello() {
return "Hello";
}
}

View File

@@ -0,0 +1,22 @@
package com.baeldung.junit5.bean;
/**
* Bean that contains utility methods to work with numbers.
*
* @author Donato Rimenti
*
*/
public class NumbersBean {
/**
* Returns true if a number is even, false otherwise.
*
* @param number
* the number to check
* @return true if the argument is even, false otherwise
*/
public boolean isNumberEven(int number) {
return number % 2 == 0;
}
}

View File

@@ -0,0 +1,7 @@
CREATE TABLE EMPLOYEE
(
ID int NOT NULL PRIMARY KEY,
FIRST_NAME varchar(255),
LAST_NAME varchar(255),
ADDRESS varchar(255),
);

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"
>
<bean id="employeeDao" class="org.baeldung.jdbc.EmployeeDAO">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<context:property-placeholder location="jdbc.properties"/>
</beans>

View File

@@ -0,0 +1,7 @@
INSERT INTO EMPLOYEE VALUES (1, 'James', 'Gosling', 'Canada');
INSERT INTO EMPLOYEE VALUES (2, 'Donald', 'Knuth', 'USA');
INSERT INTO EMPLOYEE VALUES (3, 'Linus', 'Torvalds', 'Finland');
INSERT INTO EMPLOYEE VALUES (4, 'Dennis', 'Ritchie', 'USA');

View File

@@ -0,0 +1,40 @@
package com.baeldung;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;
public class ExceptionUnitTest {
@Test
void shouldThrowException() {
Throwable exception = assertThrows(UnsupportedOperationException.class, () -> {
throw new UnsupportedOperationException("Not supported");
});
assertEquals(exception.getMessage(), "Not supported");
}
@Test
void assertThrowsException() {
String str = null;
assertThrows(IllegalArgumentException.class, () -> {
Integer.valueOf(str);
});
}
@Test
public void whenModifyMapDuringIteration_thenThrowExecption() {
Map<Integer, String> hashmap = new HashMap<>();
hashmap.put(1, "One");
hashmap.put(2, "Two");
Executable executable = () -> hashmap.forEach((key, value) -> hashmap.remove(1));
assertThrows(ConcurrentModificationException.class, executable);
}
}

View File

@@ -0,0 +1,33 @@
package com.baeldung;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
class FirstUnitTest {
@Test
void lambdaExpressions() {
List<Integer> numbers = Arrays.asList(1, 2, 3);
assertTrue(numbers.stream()
.mapToInt(i -> i)
.sum() > 5, "Sum should be greater than 5");
}
@Disabled("test to show MultipleFailuresError")
@Test
void groupAssertions() {
int[] numbers = { 0, 1, 2, 3, 4 };
assertAll("numbers", () -> assertEquals(numbers[0], 1), () -> assertEquals(numbers[3], 3), () -> assertEquals(numbers[4], 1));
}
@Test
@Disabled
void disabledTest() {
assertTrue(false);
}
}

Some files were not shown because too many files have changed in this diff Show More