Merge branch 'master' of github.com:eugenp/tutorials into master

This commit is contained in:
Karsten Silz 2020-09-19 16:50:23 +01:00
commit c75c665255
82 changed files with 1122 additions and 98 deletions

View File

@ -5,3 +5,4 @@ This module contains articles about AWS Lambda
### Relevant Articles:
- [Using AWS Lambda with API Gateway](https://www.baeldung.com/aws-lambda-api-gateway)
- [Introduction to AWS Serverless Application Model](https://www.baeldung.com/aws-serverless)
- [How to Implement Hibernate in an AWS Lambda Function in Java](https://www.baeldung.com/java-aws-lambda-hibernate)

122
core-groovy-strings/pom.xml Normal file
View File

@ -0,0 +1,122 @@
<?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>core-groovy-strings</artifactId>
<version>1.0-SNAPSHOT</version>
<name>core-groovy-strings</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>${groovy-all.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-dateutil</artifactId>
<version>${groovy.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-sql</artifactId>
<version>${groovy-sql.version}</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>${spock-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>${gmavenplus-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>addSources</goal>
<goal>addTestSources</goal>
<goal>compile</goal>
<goal>compileTests</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>${junit.platform.version}</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>junit5</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<includes>
<include>**/*Test5.java</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>central</id>
<url>https://jcenter.bintray.com</url>
</repository>
</repositories>
<properties>
<junit.platform.version>1.0.0</junit.platform.version>
<groovy.version>2.5.6</groovy.version>
<groovy-all.version>2.5.6</groovy-all.version>
<groovy-sql.version>2.5.6</groovy-sql.version>
<hsqldb.version>2.4.0</hsqldb.version>
<spock-core.version>1.1-groovy-2.4</spock-core.version>
<gmavenplus-plugin.version>1.6</gmavenplus-plugin.version>
</properties>
</project>

View File

@ -0,0 +1,70 @@
package com.baeldung.removeprefix
import org.junit.Assert
import org.junit.Test
class RemovePrefixTest {
@Test
public void whenCasePrefixIsRemoved_thenReturnTrue() {
def trimPrefix = {
it.startsWith('Groovy-') ? it.minus('Groovy-') : it
}
def actual = trimPrefix("Groovy-Tutorials at Baeldung")
def expected = "Tutorials at Baeldung"
Assert.assertEquals(expected, actual)
}
@Test
public void whenPrefixIsRemoved_thenReturnTrue() {
String prefix = "groovy-"
String trimPrefix = "Groovy-Tutorials at Baeldung"
def actual;
if(trimPrefix.startsWithIgnoreCase(prefix)) {
actual = trimPrefix.substring(prefix.length())
}
def expected = "Tutorials at Baeldung"
Assert.assertEquals(expected, actual)
}
@Test
public void whenPrefixIsRemovedUsingRegex_thenReturnTrue() {
def regex = ~"^([Gg])roovy-"
String trimPrefix = "Groovy-Tutorials at Baeldung"
String actual = trimPrefix - regex
def expected = "Tutorials at Baeldung"
Assert.assertEquals(expected, actual)
}
@Test
public void whenPrefixIsRemovedUsingReplaceFirst_thenReturnTrue() {
def regex = ~"^groovy"
String trimPrefix = "groovyTutorials at Baeldung's groovy page"
String actual = trimPrefix.replaceFirst(regex, "")
def expected = "Tutorials at Baeldung's groovy page"
Assert.assertEquals(expected, actual)
}
@Test
public void whenPrefixIsRemovedUsingReplaceAll_thenReturnTrue() {
String trimPrefix = "groovyTutorials at Baeldung groovy"
String actual = trimPrefix.replaceAll(/^groovy/, "")
def expected = "Tutorials at Baeldung groovy"
Assert.assertEquals(expected, actual)
}
}

View File

@ -6,3 +6,4 @@ This module contains complete guides about arrays in Java
- [Arrays in Java: A Reference Guide](https://www.baeldung.com/java-arrays-guide)
- [Guide to the java.util.Arrays Class](https://www.baeldung.com/java-util-arrays)
- [What is \[Ljava.lang.Object;?](https://www.baeldung.com/java-tostring-array)
- [Guide to ArrayStoreException](https://www.baeldung.com/java-arraystoreexception)

View File

@ -1,6 +1,8 @@
package com.baeldung.date;
import static org.junit.Assert.assertEquals;
import org.joda.time.Days;
import org.joda.time.Minutes;
import org.junit.Test;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@ -16,7 +18,7 @@ import java.util.Locale;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
import static org.junit.Assert.*;
public class DateDiffUnitTest {
@ -29,18 +31,39 @@ public class DateDiffUnitTest {
long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime());
long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
assertEquals(diff, 6);
assertEquals(6, diff);
}
@Test
public void givenTwoDatesInJava8_whenDifferentiating_thenWeGetSix() {
LocalDate now = LocalDate.now();
LocalDate sixDaysBehind = now.minusDays(6);
public void givenTwoDatesInJava8_whenUsingPeriodGetDays_thenWorks() {
LocalDate aDate = LocalDate.of(2020, 9, 11);
LocalDate sixDaysBehind = aDate.minusDays(6);
Period period = Period.between(now, sixDaysBehind);
Period period = Period.between(aDate, sixDaysBehind);
int diff = Math.abs(period.getDays());
assertEquals(diff, 6);
assertEquals(6, diff);
}
@Test
public void givenTwoDatesInJava8_whenUsingPeriodGetDays_thenDoesNotWork() {
LocalDate aDate = LocalDate.of(2020, 9, 11);
LocalDate sixtyDaysBehind = aDate.minusDays(60);
Period period = Period.between(aDate, sixtyDaysBehind);
int diff = Math.abs(period.getDays());
//not equals
assertNotEquals(60, diff);
}
@Test
public void givenTwoDatesInJava8_whenUsingPeriod_thenWeGet0Year1Month29Days() {
LocalDate aDate = LocalDate.of(2020, 9, 11);
LocalDate sixtyDaysBehind = aDate.minusDays(60);
Period period = Period.between(aDate, sixtyDaysBehind);
int years = Math.abs(period.getYears());
int months = Math.abs(period.getMonths());
int days = Math.abs(period.getDays());
assertArrayEquals(new int[] { 0, 1, 29 }, new int[] { years, months, days });
}
@Test
@ -51,7 +74,7 @@ public class DateDiffUnitTest {
Duration duration = Duration.between(now, sixMinutesBehind);
long diff = Math.abs(duration.toMinutes());
assertEquals(diff, 6);
assertEquals(6, diff);
}
@Test
@ -61,7 +84,7 @@ public class DateDiffUnitTest {
long diff = ChronoUnit.SECONDS.between(now, tenSecondsLater);
assertEquals(diff, 10);
assertEquals(10, diff);
}
@Test
@ -69,9 +92,9 @@ public class DateDiffUnitTest {
LocalDateTime ldt = LocalDateTime.now();
ZonedDateTime now = ldt.atZone(ZoneId.of("America/Montreal"));
ZonedDateTime sixDaysBehind = now.withZoneSameInstant(ZoneId.of("Asia/Singapore"))
.minusDays(6);
.minusDays(6);
long diff = ChronoUnit.DAYS.between(sixDaysBehind, now);
assertEquals(diff, 6);
assertEquals(6, diff);
}
@Test
@ -81,7 +104,7 @@ public class DateDiffUnitTest {
long diff = now.until(tenSecondsLater, ChronoUnit.SECONDS);
assertEquals(diff, 10);
assertEquals(10, diff);
}
@Test
@ -89,10 +112,9 @@ public class DateDiffUnitTest {
org.joda.time.LocalDate now = org.joda.time.LocalDate.now();
org.joda.time.LocalDate sixDaysBehind = now.minusDays(6);
org.joda.time.Period period = new org.joda.time.Period(now, sixDaysBehind);
long diff = Math.abs(period.getDays());
long diff = Math.abs(Days.daysBetween(now, sixDaysBehind).getDays());
assertEquals(diff, 6);
assertEquals(6, diff);
}
@Test
@ -100,8 +122,9 @@ public class DateDiffUnitTest {
org.joda.time.LocalDateTime now = org.joda.time.LocalDateTime.now();
org.joda.time.LocalDateTime sixMinutesBehind = now.minusMinutes(6);
org.joda.time.Period period = new org.joda.time.Period(now, sixMinutesBehind);
long diff = Math.abs(period.getDays());
long diff = Math.abs(Minutes.minutesBetween(now, sixMinutesBehind).getMinutes());
assertEquals(6, diff);
}
@Test
@ -111,6 +134,6 @@ public class DateDiffUnitTest {
long diff = Math.abs(now.numDaysFrom(sixDaysBehind));
assertEquals(diff, 6);
assertEquals(6, diff);
}
}
}

View File

@ -1,3 +1,5 @@
### Relevant Articles:
- [NoSuchMethodError in Java](https://www.baeldung.com/java-nosuchmethod-error)
- [IllegalArgumentException or NullPointerException for a Null Parameter?](https://www.baeldung.com/java-illegalargumentexception-or-nullpointerexception)
- [IllegalMonitorStateException in Java](https://www.baeldung.com/java-illegalmonitorstateexception)

View File

@ -10,4 +10,5 @@ This module contains articles about core Java input and output (IO)
- [Copy a Directory in Java](https://www.baeldung.com/java-copy-directory)
- [Java Files Open Options](https://www.baeldung.com/java-file-options)
- [Creating Temporary Directories in Java](https://www.baeldung.com/java-temp-directories)
- [Reading a Line at a Given Line Number From a File in Java](https://www.baeldung.com/java-read-line-at-number)
- [[<-- Prev]](/core-java-modules/core-java-io-2)

View File

@ -5,4 +5,5 @@ This module contains articles about core features in the Java language
- [Class.isInstance vs Class.isAssignableFrom](https://www.baeldung.com/java-isinstance-isassignablefrom)
- [Converting a Java String Into a Boolean](https://www.baeldung.com/java-string-to-boolean)
- [When are Static Variables Initialized in Java?](https://www.baeldung.com/java-static-variables-initialization)
- [Checking if a Class Exists in Java](https://www.baeldung.com/java-check-class-exists)
- [[<-- Prev]](/core-java-modules/core-java-lang-2)

View File

@ -13,4 +13,5 @@
- [Convert Latitude and Longitude to a 2D Point in Java](https://www.baeldung.com/java-convert-latitude-longitude)
- [Debugging with Eclipse](https://www.baeldung.com/eclipse-debugging)
- [Matrix Multiplication in Java](https://www.baeldung.com/java-matrix-multiplication)
- [Largest Power of 2 That Is Less Than the Given Number](https://www.baeldung.com/java-largest-power-of-2-less-than-number)
- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-math)

View File

@ -2,6 +2,6 @@
This module contains articles about core Kotlin collections.
### Relevant articles:
## Relevant articles:
- [Aggregate Operations in Kotlin](https://www.baeldung.com/kotlin/aggregate-operations)

View File

@ -0,0 +1,3 @@
## Relevant Articles:
- [Passing Command Line Arguments in Gradle](https://www.baeldung.com/gradle-command-line-arguments)

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Gradle Source Sets](https://www.baeldung.com/gradle-source-sets)

View File

@ -11,3 +11,4 @@ This module contains articles about security libraries.
- [Intro to Jasypt](https://www.baeldung.com/jasypt)
- [Digital Signatures in Java](https://www.baeldung.com/java-digital-signature)
- [How to Read PEM File to Get Public and Private Keys](https://www.baeldung.com/java-read-pem-file-keys)
- [SSH Connection With Java](https://www.baeldung.com/java-ssh-connection)

View File

@ -12,3 +12,4 @@ This module contains articles about test libraries.
- [Introduction to Hoverfly in Java](https://www.baeldung.com/hoverfly)
- [Testing with Hamcrest](https://www.baeldung.com/java-junit-hamcrest-guide)
- [Introduction To DBUnit](https://www.baeldung.com/java-dbunit)
- [Introduction to ArchUnit](https://www.baeldung.com/java-archunit-intro)

View File

@ -1,3 +1,4 @@
### Relevant Articles:
- [Service Locator Pattern](https://www.baeldung.com/java-service-locator-pattern)
- [The DAO Pattern in Java](https://www.baeldung.com/java-dao-pattern)
- [DAO vs Repository Patterns](https://www.baeldung.com/java-dao-vs-repository)

View File

@ -1,3 +1,4 @@
### Relevant Articles:
- [Database Migrations with Flyway](http://www.baeldung.com/database-migrations-with-flyway)
- [A Guide to Flyway Callbacks](http://www.baeldung.com/flyway-callbacks)
- [Rolling Back Migrations with Flyway](https://www.baeldung.com/flyway-roll-back)

View File

@ -383,6 +383,7 @@
<module>core-groovy</module>
<module>core-groovy-2</module>
<module>core-groovy-collections</module>
<module>core-groovy-strings</module>
<module>core-java-modules</module>
<module>core-kotlin-modules</module>
@ -894,6 +895,7 @@
<module>core-groovy</module>
<module>core-groovy-2</module>
<module>core-groovy-collections</module>
<module>core-groovy-strings</module>
<module>core-java-modules</module>
<module>core-kotlin-modules</module>

View File

@ -1,3 +1,4 @@
## Relevant Articles:
- [Guide to QuarkusIO](https://www.baeldung.com/quarkus-io)
- [Testing Quarkus Applications](https://www.baeldung.com/java-quarkus-testing)

View File

@ -99,6 +99,8 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
<systemProperties>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
</systemProperties>

View File

@ -7,3 +7,4 @@ This module contains articles about Spring 5 OAuth Security
- [Spring Security 5 OAuth2 Login](https://www.baeldung.com/spring-security-5-oauth2-login)
- [Extracting Principal and Authorities using Spring Security OAuth](https://www.baeldung.com/spring-security-oauth-principal-authorities-extractor)
- [Customizing Authorization and Token Requests with Spring Security 5.1 Client](https://www.baeldung.com/spring-security-custom-oauth-requests)
- [Social Login with Spring Security in a Jersey Application](https://www.baeldung.com/spring-security-social-login-jersey)

View File

@ -0,0 +1,29 @@
package com.baeldung.inmemory;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
//@Configuration
public class InMemoryNoOpAuthWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("spring")
.password("{noop}secret")
.roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/private/**")
.authenticated()
.antMatchers("/public/**")
.permitAll()
.and()
.httpBasic();
}
}

View File

@ -8,3 +8,4 @@ This module contains articles about Spring 5 WebFlux
- [How to Return 404 with Spring WebFlux](https://www.baeldung.com/spring-webflux-404)
- [Spring WebClient Requests with Parameters](https://www.baeldung.com/webflux-webclient-parameters)
- [RSocket Using Spring Boot](https://www.baeldung.com/spring-boot-rsocket)
- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux)

View File

@ -9,3 +9,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Liveness and Readiness Probes in Spring Boot](https://www.baeldung.com/spring-liveness-readiness-probes)
- [Custom Information in Spring Boot Info Endpoint](https://www.baeldung.com/spring-boot-info-actuator-custom)
- [Health Indicators in Spring Boot](https://www.baeldung.com/spring-boot-health-indicators)

View File

@ -10,4 +10,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Create a Custom Auto-Configuration with Spring Boot](https://www.baeldung.com/spring-boot-custom-auto-configuration)
- [Guide to ApplicationContextRunner in Spring Boot](https://www.baeldung.com/spring-boot-context-runner)
- [A Guide to Spring Boot Configuration Metadata](https://www.baeldung.com/spring-boot-configuration-metadata)
- [Display Auto-Configuration Report in Spring Boot](https://www.baeldung.com/spring-boot-auto-configuration-report)
- [Display Auto-Configuration Report in Spring Boot](https://www.baeldung.com/spring-boot-auto-configuration-report)
- [The Spring @ConditionalOnProperty Annotation](https://www.baeldung.com/spring-conditionalonproperty)

View File

@ -14,15 +14,7 @@
<packaging>jar</packaging>
<name>spring-boot-exceptions</name>
<description>Demo project for working with Spring Boot exceptions</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>
</dependencies>
<description>Demo project for working with Spring Boot exceptions</description>
<build>
<finalName>spring-boot-exceptions</finalName>
@ -32,68 +24,6 @@
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>autoconfiguration</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*LiveTest.java</exclude>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*IntTest.java</exclude>
</excludes>
<includes>
<include>**/AutoconfigurationTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<!-- The main class to start by executing java -jar -->
<start-class>com.baeldung.intro.App</start-class>
<spring-boot.version>2.2.3.RELEASE</spring-boot.version>
</properties>
</project>

View File

@ -4,3 +4,4 @@ This module contains articles about Keycloak in Spring Boot projects.
## Relevant articles:
- [A Quick Guide to Using Keycloak with Spring Boot](https://www.baeldung.com/spring-boot-keycloak)
- [Custom User Attributes with Keycloak](https://www.baeldung.com/keycloak-custom-user-attributes)

View File

@ -6,4 +6,5 @@ This module contains articles about Spring Web MVC in Spring Boot projects.
- [Circular View Path Error](https://www.baeldung.com/spring-circular-view-path-error)
- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file)
- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux)
- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2)

View File

@ -22,6 +22,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
@ -37,4 +41,4 @@
<commons-io.version>2.7</commons-io.version>
</properties>
</project>
</project>

View File

@ -0,0 +1,12 @@
package com.baeldung.springvalidation;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
public class ServletInitializer extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SpringValidationApplication.class);
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.springvalidation;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringValidationApplication {
public static void main(String[] args) {
SpringApplication.run(SpringValidationApplication.class, args);
}
}

View File

@ -0,0 +1,44 @@
package com.baeldung.springvalidation.controller;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.baeldung.springvalidation.domain.UserAccount;
import com.baeldung.springvalidation.interfaces.BasicInfo;
@Controller
public class UserAccountController {
@GetMapping("/getUserForm")
public String showUserForm(Model theModel) {
UserAccount theUser = new UserAccount();
theModel.addAttribute("useraccount", theUser);
return "userHome";
}
@RequestMapping(value = "/saveBasicInfo", method = RequestMethod.POST)
public String saveBasicInfo(@Valid @ModelAttribute("useraccount") UserAccount useraccount, BindingResult result, ModelMap model) {
if (result.hasErrors()) {
return "error";
}
return "success";
}
@RequestMapping(value = "/saveBasicInfoStep1", method = RequestMethod.POST)
public String saveBasicInfoStep1(@Validated(BasicInfo.class) @ModelAttribute("useraccount") UserAccount useraccount, BindingResult result, ModelMap model) {
if (result.hasErrors()) {
return "error";
}
return "success";
}
}

View File

@ -0,0 +1,80 @@
package com.baeldung.springvalidation.domain;
import javax.validation.Valid;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.baeldung.springvalidation.interfaces.AdvanceInfo;
import com.baeldung.springvalidation.interfaces.BasicInfo;
public class UserAccount {
@NotNull(groups = BasicInfo.class)
@Size(min = 4, max = 15, groups = BasicInfo.class)
private String password;
@NotBlank(groups = BasicInfo.class)
private String name;
@Min(value = 18, message = "Age should not be less than 18", groups = AdvanceInfo.class)
private int age;
@NotBlank(groups = AdvanceInfo.class)
private String phone;
@Valid
@NotNull(groups = AdvanceInfo.class)
private UserAddress useraddress;
public UserAddress getUseraddress() {
return useraddress;
}
public void setUseraddress(UserAddress useraddress) {
this.useraddress = useraddress;
}
public UserAccount() {
}
public UserAccount(String email, String password, String name, int age) {
this.password = password;
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.springvalidation.domain;
import javax.validation.constraints.NotBlank;
public class UserAddress {
@NotBlank
private String countryCode;
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
}

View File

@ -0,0 +1,6 @@
package com.baeldung.springvalidation.interfaces;
public interface AdvanceInfo {
// validation group marker interface
}

View File

@ -0,0 +1,6 @@
package com.baeldung.springvalidation.interfaces;
public interface BasicInfo {
// validation group marker interface
}

View File

@ -0,0 +1,2 @@
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.html

View File

@ -0,0 +1,10 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>SpringValidation</title>
</head>
<body>
<h3>Error!!!</h3>
</body>
</html>

View File

@ -0,0 +1,10 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>SpringValidation</title>
</head>
<body>
<h3>SUCCESS!!!</h3>
</body>
</html>

View File

@ -0,0 +1,57 @@
package com.baeldung.springvalidation;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class UserAccountUnitTest {
@Autowired
private MockMvc mockMvc;
@Test
public void givenSaveBasicInfo_whenCorrectInput_thenSuccess() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/saveBasicInfo")
.accept(MediaType.TEXT_HTML)
.param("name", "test123")
.param("password", "pass"))
.andExpect(view().name("success"))
.andExpect(status().isOk())
.andDo(print());
}
@Test
public void givenSaveBasicInfoStep1_whenCorrectInput_thenSuccess() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/saveBasicInfoStep1")
.accept(MediaType.TEXT_HTML)
.param("name", "test123")
.param("password", "pass"))
.andExpect(view().name("success"))
.andExpect(status().isOk())
.andDo(print());
}
@Test
public void givenSaveBasicInfoStep1_whenIncorrectInput_thenError() throws Exception {
this.mockMvc.perform(MockMvcRequestBuilders.post("/saveBasicInfoStep1")
.accept(MediaType.TEXT_HTML))
// .param("name", "test123")
// .param("password", "pass"))
.andExpect(model().errorCount(2))
// .andExpect(view().name("error"))
.andExpect(status().isOk())
.andDo(print());
}
}

View File

@ -6,4 +6,4 @@
### Relevant Articles:
- [How to Define a Map in YAML for a POJO?](https://www.baeldung.com/yaml-map-pojo)
- [Using application.yml vs application.properties in Spring Boot](https://www.baeldung.com/spring-boot-yaml-vs-properties)

View File

@ -0,0 +1,3 @@
## Relevant Articles:
- [Hiding Endpoints From Swagger Documentation in Spring Boot](https://www.baeldung.com/spring-swagger-hiding-endpoints)

View File

@ -1,3 +1,4 @@
### Relevant Articles:
- [A Quick Guide to Spring Cloud Consul](http://www.baeldung.com/spring-cloud-consul)
- [Leadership Election With Consul](https://www.baeldung.com/consul-leadership-election)

View File

@ -0,0 +1,36 @@
package com.baeldung.jsonparams.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.baeldung.jsonparams" })
public class JsonParamsConfig implements WebMvcConfigurer {
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setPrefix("/WEB-INF/");
bean.setSuffix(".jsp");
return bean;
}
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.jsonparams.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
public class JsonParamsInit // implements WebApplicationInitializer
{
//uncomment to run the product controller example
//@Override
public void onStartup(ServletContext sc) throws ServletException {
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.register(JsonParamsConfig.class);
root.setServletContext(sc);
sc.addListener(new ContextLoaderListener(root));
DispatcherServlet dv = new DispatcherServlet(root);
ServletRegistration.Dynamic appServlet = sc.addServlet("jsonparams-mvc", dv);
appServlet.setLoadOnStartup(1);
appServlet.addMapping("/");
}
}

View File

@ -0,0 +1,57 @@
package com.baeldung.jsonparams.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.baeldung.jsonparams.model.Product;
import com.baeldung.jsonparams.propertyeditor.ProductEditor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@Controller
@RequestMapping("/products")
public class ProductController {
private ObjectMapper objectMapper;
@Autowired
public void setObjectMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Product.class, new ProductEditor(objectMapper));
}
@PostMapping("/create")
@ResponseBody
public Product createProduct(@RequestBody Product product) {
// custom logic
return product;
}
@GetMapping("/get")
@ResponseBody
public Product getProduct(@RequestParam String product) throws JsonMappingException, JsonProcessingException {
final Product prod = objectMapper.readValue(product, Product.class);
return prod;
}
@GetMapping("/get2")
@ResponseBody
public Product get2Product(@RequestParam Product product) {
// custom logic
return product;
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.jsonparams.model;
public class Product {
private int id;
private String name;
private double price;
public Product() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String nom) {
this.name = nom;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung.jsonparams.propertyeditor;
import java.beans.PropertyEditorSupport;
import org.springframework.util.StringUtils;
import com.baeldung.jsonparams.model.Product;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class ProductEditor extends PropertyEditorSupport {
private ObjectMapper objectMapper;
public ProductEditor(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.isEmpty(text)) {
setValue(null);
} else {
Product prod = new Product();
try {
prod = objectMapper.readValue(text, Product.class);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException(e);
}
setValue(prod);
}
}
}

View File

@ -0,0 +1,71 @@
package com.baeldung.jsonparams;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.AnnotationConfigWebContextLoader;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import com.baeldung.jsonparams.config.JsonParamsConfig;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = { JsonParamsConfig.class }, loader = AnnotationConfigWebContextLoader.class)
public class JsonParamsIntegrationTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext wac;
@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
.build();
}
@Test
public void whenJsonIsPassedWithPost_thenResponseOK() throws Exception {
this.mockMvc.perform(post("/products/create").accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content("{\"id\": 1,\"name\": \"Asus Zenbook\",\"price\": 800}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value("1"))
.andExpect(jsonPath("$.name").value("Asus Zenbook"));
}
@Test
public void whenJsonIsPassedWithGet_thenResponseOK() throws Exception {
this.mockMvc.perform(get("/products/get").contentType(MediaType.APPLICATION_JSON)
.queryParam("product", "{\"id\": 2,\"name\": \"HP EliteBook\",\"price\": 700}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value("2"))
.andExpect(jsonPath("$.name").value("HP EliteBook"));
}
@Test
public void whenJsonIsPassedWithGet2_thenResponseOK() throws Exception {
this.mockMvc.perform(get("/products/get2").contentType(MediaType.APPLICATION_JSON)
.queryParam("product", "{\"id\": 3,\"name\": \"Dell G5 15\",\"price\": 1200}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value("3"))
.andExpect(jsonPath("$.name").value("Dell G5 15"));
}
}

View File

@ -7,4 +7,4 @@ The "REST With Spring 2" Classes: http://bit.ly/restwithspring
### Relevant Articles:
- [How to Turn Off Swagger-ui in Production](https://www.baeldung.com/swagger-ui-turn-off-in-production)

View File

@ -14,3 +14,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Guide to DeferredResult in Spring](https://www.baeldung.com/spring-deferred-result)
- [Using JSON Patch in Spring REST APIs](https://www.baeldung.com/spring-rest-json-patch)
- [OpenAPI JSON Objects as Query Parameters](https://www.baeldung.com/openapi-json-query-parameters)
- [Dates in OpenAPI Files](https://www.baeldung.com/openapi-dates)

View File

@ -8,3 +8,4 @@ This module contains articles about Spring with Thymeleaf
- [Formatting Currencies in Spring Using Thymeleaf](https://www.baeldung.com/spring-thymeleaf-currencies)
- [Working with Select and Option in Thymeleaf](https://www.baeldung.com/thymeleaf-select-option)
- [Conditional CSS Classes in Thymeleaf](https://www.baeldung.com/spring-mvc-thymeleaf-conditional-css-classes)
- [Using Hidden Inputs with Spring and Thymeleaf](https://www.baeldung.com/spring-thymeleaf-hidden-inputs)

View File

@ -8,3 +8,4 @@
- [Introduction to Mockitos AdditionalAnswers](https://www.baeldung.com/mockito-additionalanswers)
- [Mockito Using Spies](https://www.baeldung.com/mockito-spy)
- [Using Mockito ArgumentCaptor](https://www.baeldung.com/mockito-argumentcaptor)
- [Difference Between when() and doXxx() Methods in Mockito](https://www.baeldung.com/java-mockito-when-vs-do)

View File

@ -41,7 +41,8 @@
<module>junit-5-advanced</module>
<module>xmlunit-2</module>
<module>junit-4</module>
<module>testing-libraries</module>
<module>testing-libraries</module>
<module>testing-libraries-2</module>
<module>powermock</module>
</modules>

View File

@ -1 +1,3 @@
## Relevant Articles:
- [Guide to @DynamicPropertySource in Spring](https://www.baeldung.com/spring-dynamicpropertysource)

View File

@ -1,3 +1,4 @@
### Relevant Articles:
- [Asserting Log Messages With JUnit](https://www.baeldung.com/junit-asserting-logs)
- [Assert Two Lists for Equality Ignoring Order in Java](https://www.baeldung.com/java-assert-lists-equality-ignore-order)

View File

@ -0,0 +1,43 @@
<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>testing-libraries-2</artifactId>
<name>testing-libraries-2</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>testing-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>${system-rules.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-lambda</artifactId>
<version>${system-lambda.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>testing-libraries</finalName>
<resources>
<resource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<properties>
<system-rules.version>1.19.0</system-rules.version>
<system-lambda.version>1.0.0</system-lambda.version>
</properties>
</project>

View File

@ -0,0 +1,19 @@
package com.baeldung.systemrules;
import static org.junit.Assert.assertNull;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.ClearSystemProperties;
public class ClearSystemPropertiesWithRuleUnitTest {
@Rule
public final ClearSystemProperties userNameIsClearedRule = new ClearSystemProperties("user.name");
@Test
public void givenClearUsernameProperty_whenGetUserName_thenNull() {
assertNull(System.getProperty("user.name"));
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.systemrules;
import static com.github.stefanbirkner.systemlambda.SystemLambda.restoreSystemProperties;
import static org.junit.Assert.assertEquals;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
class ProvidesSystemPropertyUnitTest {
@BeforeAll
static void setUpBeforeClass() throws Exception {
System.setProperty("log_dir", "/tmp/baeldung/logs");
}
@Test
void givenSetSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully() throws Exception {
restoreSystemProperties(() -> {
System.setProperty("log_dir", "test/resources");
assertEquals("log_dir should be provided", "test/resources", System.getProperty("log_dir"));
});
assertEquals("log_dir should be provided", "/tmp/baeldung/logs", System.getProperty("log_dir"));
}
}

View File

@ -0,0 +1,44 @@
package com.baeldung.systemrules;
import static org.junit.Assert.assertEquals;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.ProvideSystemProperty;
public class ProvidesSystemPropertyWithRuleUnitTest {
@Rule
public final ProvideSystemProperty providesSystemPropertyRule = new ProvideSystemProperty("log_dir", "test/resources").and("another_property", "another_value");
@Rule
public final ProvideSystemProperty providesSystemPropertyFromFileRule = ProvideSystemProperty.fromResource("/test.properties");
@BeforeClass
public static void setUpBeforeClass() {
setLogs();
}
@AfterClass
public static void tearDownAfterClass() throws Exception {
System.out.println(System.getProperty("log_dir"));
}
@Test
public void givenProvideSystemProperty_whenGetLogDir_thenLogDirIsProvidedSuccessfully() {
assertEquals("log_dir should be provided", "test/resources", System.getProperty("log_dir"));
}
@Test
public void givenProvideSystemPropertyFromFile_whenGetName_thenNameIsProvidedSuccessfully() {
assertEquals("name should be provided", "baeldung", System.getProperty("name"));
assertEquals("version should be provided", "1.0", System.getProperty("version"));
}
private static void setLogs() {
System.setProperty("log_dir", "/tmp/baeldung/logs");
}
}

View File

@ -0,0 +1,24 @@
package com.baeldung.systemrules;
import static com.github.stefanbirkner.systemlambda.SystemLambda.tapSystemErr;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
class SystemErrPrintlnUnitTest {
@Test
void givenTapSystemErr_whenInvokePrintln_thenOutputIsReturnedSuccessfully() throws Exception {
String text = tapSystemErr(() -> {
printError("An error occurred Baeldung Readers!!");
});
Assert.assertEquals("An error occurred Baeldung Readers!!", text.trim());
}
private void printError(String output) {
System.err.println(output);
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.systemrules;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.SystemErrRule;
public class SystemErrPrintlnWithRuleUnitTest {
@Rule
public final SystemErrRule systemErrRule = new SystemErrRule().enableLog();
@Test
public void givenSystemErrRule_whenInvokePrintln_thenLogSuccess() {
printError("An Error occurred Baeldung Readers!!");
Assert.assertEquals("An Error occurred Baeldung Readers!!", systemErrRule.getLog()
.trim());
}
private void printError(String output) {
System.err.println(output);
}
}

View File

@ -0,0 +1,23 @@
package com.baeldung.systemrules;
import static org.junit.Assert.assertEquals;
import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit;
import org.junit.jupiter.api.Test;
class SystemExitUnitTest {
@Test
void givenCatchSystemExit_whenAppCallsSystemExit_thenStatusIsReturnedSuccessfully() throws Exception {
int statusCode = catchSystemExit(() -> {
exit();
});
assertEquals("status code should be 1:", 1, statusCode);
}
private void exit() {
System.exit(1);
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.systemrules;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;
public class SystemExitWithRuleUnitTest {
@Rule
public final ExpectedSystemExit exitRule = ExpectedSystemExit.none();
@Test
public void givenSystemExitRule_whenAppCallsSystemExit_thenExitRuleWorkssAsExpected() {
exitRule.expectSystemExitWithStatus(1);
exit();
}
private void exit() {
System.exit(1);
}
}

View File

@ -0,0 +1,27 @@
package com.baeldung.systemrules;
import static com.github.stefanbirkner.systemlambda.SystemLambda.withTextFromSystemIn;
import static org.junit.Assert.assertEquals;
import java.util.Scanner;
import org.junit.jupiter.api.Test;
class SystemInUnitTest {
@Test
void givenTwoNames_whenSystemInMock_thenNamesJoinedTogether() throws Exception {
withTextFromSystemIn("Jonathan", "Cook").execute(() -> {
assertEquals("Names should be concatenated", "Jonathan Cook", getFullname());
});
}
private String getFullname() {
try (Scanner scanner = new Scanner(System.in)) {
String firstName = scanner.next();
String surname = scanner.next();
return String.join(" ", firstName, surname);
}
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.systemrules;
import static org.junit.Assert.assertEquals;
import java.util.Scanner;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.TextFromStandardInputStream;
import static org.junit.contrib.java.lang.system.TextFromStandardInputStream.emptyStandardInputStream;
public class SystemInWithRuleUnitTest {
@Rule
public final TextFromStandardInputStream systemInMock = emptyStandardInputStream();
@Test
public void givenTwoNames_whenSystemInMock_thenNamesJoinedTogether() {
systemInMock.provideLines("Jonathan", "Cook");
assertEquals("Names should be concatenated", "Jonathan Cook", getFullname());
}
private String getFullname() {
try (Scanner scanner = new Scanner(System.in)) {
String firstName = scanner.next();
String surname = scanner.next();
return String.join(" ", firstName, surname);
}
}
}

View File

@ -0,0 +1,2 @@
name=baeldung
version=1.0