diff --git a/pact/pact-spring-provider/build.gradle b/pact/pact-spring-provider/build.gradle index 7dd81f1..8bb7749 100644 --- a/pact/pact-spring-provider/build.gradle +++ b/pact/pact-spring-provider/build.gradle @@ -26,7 +26,7 @@ dependencies { compile('org.springframework.boot:spring-boot-starter-data-jpa') compile('org.springframework.boot:spring-boot-starter-web') compile('com.h2database:h2:1.4.196') - testCompile('au.com.dius:pact-jvm-provider-spring_2.12:3.5.11') + testCompile('au.com.dius:pact-jvm-provider-spring_2.12:3.5.16') testCompile('junit:junit:4.12') testCompile('org.springframework.boot:spring-boot-starter-test') } diff --git a/settings.gradle b/settings.gradle index 6c22d40..fae6ca9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,6 +17,7 @@ include 'spring-boot:rabbitmq-event-brokering' include 'spring-boot:modular:security-module' include 'spring-boot:modular:booking-module' include 'spring-boot:modular:application' +include 'spring-boot:spring-boot-testing' include 'junit:conditions' diff --git a/spring-boot/spring-boot-testing/.gitignore b/spring-boot/spring-boot-testing/.gitignore new file mode 100644 index 0000000..2b1babb --- /dev/null +++ b/spring-boot/spring-boot-testing/.gitignore @@ -0,0 +1,27 @@ +.gradle +/build/ +!gradle/wrapper/gradle-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +/out/ + +### NetBeans ### +/nbproject/private/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file diff --git a/spring-boot/spring-boot-testing/build.gradle b/spring-boot/spring-boot-testing/build.gradle new file mode 100644 index 0000000..7745f47 --- /dev/null +++ b/spring-boot/spring-boot-testing/build.gradle @@ -0,0 +1,34 @@ +buildscript { + ext { + springBootVersion = '2.0.2.RELEASE' + } + repositories { + mavenCentral() + } + dependencies { + classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") + } +} + +apply plugin: 'java' +apply plugin: 'eclipse' +apply plugin: 'org.springframework.boot' +apply plugin: 'io.spring.dependency-management' + +group = 'reflectoring.io' +version = '0.0.1-SNAPSHOT' +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + + +dependencies { + compile('org.springframework.boot:spring-boot-starter-data-jpa') + compile('org.springframework.boot:spring-boot-starter-web') + compileOnly('org.projectlombok:lombok') + runtime('com.h2database:h2') + testCompile('org.springframework.boot:spring-boot-starter-test') + testCompile 'org.junit.jupiter:junit-jupiter-engine:5.2.0' +} diff --git a/spring-boot/spring-boot-testing/gradlew b/spring-boot/spring-boot-testing/gradlew new file mode 100644 index 0000000..4453cce --- /dev/null +++ b/spring-boot/spring-boot-testing/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save ( ) { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/spring-boot/spring-boot-testing/gradlew.bat b/spring-boot/spring-boot-testing/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/spring-boot/spring-boot-testing/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/spring-boot/spring-boot-testing/settings.gradle b/spring-boot/spring-boot-testing/settings.gradle new file mode 100644 index 0000000..5237f27 --- /dev/null +++ b/spring-boot/spring-boot-testing/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'spring-boot-testing' diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/Application.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/Application.java new file mode 100644 index 0000000..a67c3f6 --- /dev/null +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/Application.java @@ -0,0 +1,13 @@ +package io.reflectoring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/BookingConfiguration.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/BookingConfiguration.java index 3204622..652368e 100644 --- a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/BookingConfiguration.java +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/BookingConfiguration.java @@ -1,18 +1,32 @@ package io.reflectoring.booking; import io.reflectoring.booking.business.BookingService; -import org.springframework.context.annotation.Bean; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import io.reflectoring.booking.data.BookingRepository; -import io.reflectoring.customer.CustomerRepository; -import io.reflectoring.flight.FlightRepository; +import io.reflectoring.customer.CustomerConfiguration; +import io.reflectoring.customer.data.CustomerRepository; +import io.reflectoring.flight.FlightConfiguration; +import io.reflectoring.flight.data.FlightService; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; -@EnableJpaRepositories("re") +@SpringBootConfiguration +@Import({CustomerConfiguration.class, FlightConfiguration.class}) +@EnableAutoConfiguration +@ComponentScan public class BookingConfiguration { @Bean - public BookingService bookingService(BookingRepository bookingRepository, CustomerRepository customerRepository, FlightRepository flightRepository) { - return new BookingService(bookingRepository, customerRepository, flightRepository); + public BookingService bookingService( + BookingRepository bookingRepository, + CustomerRepository customerRepository, + FlightService flightService) { + return new BookingService(bookingRepository, customerRepository, flightService); } } diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/business/BookingService.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/business/BookingService.java index b253a21..64836f4 100644 --- a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/business/BookingService.java +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/business/BookingService.java @@ -4,10 +4,10 @@ import java.util.Optional; import io.reflectoring.booking.data.Booking; import io.reflectoring.booking.data.BookingRepository; -import io.reflectoring.customer.Customer; -import io.reflectoring.customer.CustomerRepository; -import io.reflectoring.flight.Flight; -import io.reflectoring.flight.FlightRepository; +import io.reflectoring.customer.data.Customer; +import io.reflectoring.customer.data.CustomerRepository; +import io.reflectoring.flight.data.Flight; +import io.reflectoring.flight.data.FlightService; public class BookingService { @@ -15,35 +15,35 @@ public class BookingService { private CustomerRepository customerRepository; - private FlightRepository flightRepository; + FlightService flightService; public BookingService( BookingRepository bookingRepository, CustomerRepository customerRepository, - FlightRepository flightRepository) { + FlightService flightService) { this.bookingRepository = bookingRepository; this.customerRepository = customerRepository; - this.flightRepository = flightRepository; + this.flightService = flightService; } /** * Books the given flight for the given customer. */ - public Booking bookFlight(Long customerId, Long flightId) { + public Booking bookFlight(Long customerId, String flightNumber) { Optional customer = customerRepository.findById(customerId); if (!customer.isPresent()) { throw new CustomerDoesNotExistException(customerId); } - Optional flight = flightRepository.findById(flightId); + Optional flight = flightService.findFlight(flightNumber); if (!flight.isPresent()) { - throw new FlightDoesNotExistException(flightId); + throw new FlightDoesNotExistException(flightNumber); } Booking booking = Booking.builder() .customer(customer.get()) - .flight(flight.get()) + .flightNumber(flight.get().getFlightNumber()) .build(); return this.bookingRepository.save(booking); diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/business/FlightDoesNotExistException.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/business/FlightDoesNotExistException.java index 5119d20..b643635 100644 --- a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/business/FlightDoesNotExistException.java +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/business/FlightDoesNotExistException.java @@ -2,8 +2,8 @@ package io.reflectoring.booking.business; class FlightDoesNotExistException extends RuntimeException { - FlightDoesNotExistException(Long flightId) { - super(String.format("A flight with ID '%d' doesn't exist!", flightId)); + FlightDoesNotExistException(String flightNumber) { + super(String.format("A flight with ID '%d' doesn't exist!", flightNumber)); } } diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/data/Booking.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/data/Booking.java index 3e47e74..593bfa2 100644 --- a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/data/Booking.java +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/data/Booking.java @@ -1,12 +1,9 @@ package io.reflectoring.booking.data; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToOne; +import javax.persistence.*; -import io.reflectoring.customer.Customer; -import io.reflectoring.flight.Flight; +import io.reflectoring.customer.data.Customer; +import io.reflectoring.flight.data.Flight; import lombok.Builder; import lombok.Data; @@ -22,7 +19,7 @@ public class Booking { @ManyToOne private Customer customer; - @ManyToOne - private Flight flight; + @Column + private String flightNumber; } diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/web/BookingController.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/web/BookingController.java index 4ef78b8..5681de2 100644 --- a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/web/BookingController.java +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/booking/web/BookingController.java @@ -1,11 +1,11 @@ package io.reflectoring.booking.web; import io.reflectoring.booking.business.BookingService; +import io.reflectoring.booking.data.Booking; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import io.reflectoring.booking.data.Booking; @RestController public class BookingController { @@ -19,19 +19,12 @@ public class BookingController { @PostMapping("/booking") public ResponseEntity bookFlight( @RequestParam("customerId") Long customerId, - @RequestParam("flightId") Long flightId) { - try { - Booking booking = bookingService.bookFlight(customerId, flightId); - BookingResultResource bookingResult = BookingResultResource.builder() - .success(true) - .build(); - return ResponseEntity.ok(bookingResult); - } catch (Exception e) { - BookingResultResource bookingResult = BookingResultResource.builder() - .success(false) - .build(); - return ResponseEntity.badRequest().body(bookingResult); - } + @RequestParam("flightNumber") String flightNumber) { + Booking booking = bookingService.bookFlight(customerId, flightNumber); + BookingResultResource bookingResult = BookingResultResource.builder() + .success(true) + .build(); + return ResponseEntity.ok(bookingResult); } } diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/CustomerConfiguration.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/CustomerConfiguration.java new file mode 100644 index 0000000..b040837 --- /dev/null +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/CustomerConfiguration.java @@ -0,0 +1,14 @@ +package io.reflectoring.customer; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; + +@SpringBootConfiguration +@EnableAutoConfiguration +@ComponentScan +public class CustomerConfiguration { + +} diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/Customer.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/data/Customer.java similarity index 70% rename from spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/Customer.java rename to spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/data/Customer.java index df24d70..aaab026 100644 --- a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/Customer.java +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/data/Customer.java @@ -1,15 +1,16 @@ -package io.reflectoring.customer; +package io.reflectoring.customer.data; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; -import lombok.Builder; -import lombok.Data; +import lombok.*; @Entity @Data @Builder +@NoArgsConstructor +@AllArgsConstructor public class Customer { @Id diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/CustomerRepository.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/data/CustomerRepository.java similarity index 56% rename from spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/CustomerRepository.java rename to spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/data/CustomerRepository.java index 4441bfb..6df3672 100644 --- a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/CustomerRepository.java +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/customer/data/CustomerRepository.java @@ -1,6 +1,11 @@ -package io.reflectoring.customer; +package io.reflectoring.customer.data; + +import java.util.List; import org.springframework.data.repository.CrudRepository; public interface CustomerRepository extends CrudRepository { + + List findByName(String name); + } diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/Flight.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/Flight.java deleted file mode 100644 index 0b5dd6f..0000000 --- a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/Flight.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.reflectoring.flight; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; - -import lombok.Builder; -import lombok.Data; - -@Entity -@Data -@Builder -public class Flight { - - @Id - @GeneratedValue - private Long id; - - private String flightNumber; - - private String airline; - -} diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/FlightConfiguration.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/FlightConfiguration.java new file mode 100644 index 0000000..0bd7d1e --- /dev/null +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/FlightConfiguration.java @@ -0,0 +1,23 @@ +package io.reflectoring.flight; + +import io.reflectoring.flight.data.FlightService; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootConfiguration +@EnableAutoConfiguration +@EnableScheduling +@ComponentScan +public class FlightConfiguration { + + @Bean + public FlightService flightService(){ + return new FlightService(); + } + +} diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/FlightRepository.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/FlightRepository.java deleted file mode 100644 index 3b09c83..0000000 --- a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/FlightRepository.java +++ /dev/null @@ -1,6 +0,0 @@ -package io.reflectoring.flight; - -import org.springframework.data.repository.CrudRepository; - -public interface FlightRepository extends CrudRepository { -} diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/data/Flight.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/data/Flight.java new file mode 100644 index 0000000..f120557 --- /dev/null +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/data/Flight.java @@ -0,0 +1,14 @@ +package io.reflectoring.flight.data; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class Flight { + + private String flightNumber; + + private String airline; + +} diff --git a/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/data/FlightService.java b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/data/FlightService.java new file mode 100644 index 0000000..ad8e1d5 --- /dev/null +++ b/spring-boot/spring-boot-testing/src/main/java/io/reflectoring/flight/data/FlightService.java @@ -0,0 +1,14 @@ +package io.reflectoring.flight.data; + +import java.util.Optional; + +public class FlightService { + + public Optional findFlight(String flightNumber) { + return Optional.of(Flight.builder() + .airline("Oceanic") + .flightNumber("815") + .build()); + } + +} diff --git a/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/ApplicationTests.java b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/ApplicationTests.java new file mode 100644 index 0000000..85bf493 --- /dev/null +++ b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/ApplicationTests.java @@ -0,0 +1,16 @@ +package io.reflectoring; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest +class ApplicationTests { + + @Test + void applicationContextLoads() { + } + +} diff --git a/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/BookingConfigurationTest.java b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/BookingConfigurationTest.java new file mode 100644 index 0000000..ff89f18 --- /dev/null +++ b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/BookingConfigurationTest.java @@ -0,0 +1,32 @@ +package io.reflectoring.booking; + +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = BookingConfiguration.class) +class BookingConfigurationTest { + + @Autowired + private ApplicationContext applicationContext; + + + @BeforeEach + void printApplicationContext() { + Arrays.stream(applicationContext.getBeanDefinitionNames()) + .map(name -> applicationContext.getBean(name).getClass().getName()) + .sorted() + .forEach(System.out::println); + } + @Test + void bookingConfigurationLoads() { + } + +} \ No newline at end of file diff --git a/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/BookingIntegrationTest.java b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/BookingIntegrationTest.java new file mode 100644 index 0000000..c5d6179 --- /dev/null +++ b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/BookingIntegrationTest.java @@ -0,0 +1,49 @@ +package io.reflectoring.booking; + +import io.reflectoring.customer.data.Customer; +import io.reflectoring.customer.data.CustomerRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +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.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@ExtendWith(SpringExtension.class) +@SpringBootTest +class BookingIntegrationTest { + + @Autowired + private WebApplicationContext applicationContext; + + @Autowired + private CustomerRepository customerRepository; + + private MockMvc mockMvc; + + @BeforeEach + void setup() { + this.mockMvc = MockMvcBuilders + .webAppContextSetup(applicationContext) + .build(); + } + + @Test + void bookFlightReturnsHttpStatusOk() throws Exception { + this.customerRepository.save(Customer.builder() + .name("Hurley") + .build()); + + this.mockMvc.perform( + post("/booking") + .param("customerId", "1") + .param("flightNumber", "Oceanic 815")) + .andExpect(status().isOk()); + } + +} diff --git a/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/business/BookingServiceTest.java b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/business/BookingServiceTest.java new file mode 100644 index 0000000..df1bd15 --- /dev/null +++ b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/business/BookingServiceTest.java @@ -0,0 +1,67 @@ +package io.reflectoring.booking.business; + +import java.util.Optional; + +import io.reflectoring.booking.data.Booking; +import io.reflectoring.booking.data.BookingRepository; +import io.reflectoring.customer.data.Customer; +import io.reflectoring.customer.data.CustomerRepository; +import io.reflectoring.flight.data.Flight; +import io.reflectoring.flight.data.FlightService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +class BookingServiceTest { + + private CustomerRepository customerRepository = Mockito.mock(CustomerRepository.class); + + private FlightService flightService = Mockito.mock(FlightService.class); + + private BookingRepository bookingRepository = Mockito.mock(BookingRepository.class); + + private BookingService bookingService; + + @BeforeEach + void setup() { + this.bookingService = new BookingService(bookingRepository, customerRepository, flightService); + } + + @Test + void bookFlightReturnsBooking() { + when(customerRepository.findById(42L)).thenReturn(customer()); + when(flightService.findFlight("Oceanic 815")).thenReturn(flight()); + when(bookingRepository.save(eq(booking()))).thenReturn(booking()); + Booking booking = bookingService.bookFlight(42L, "Oceanic 815"); + + assertThat(booking).isNotNull(); + verify(bookingRepository).save(eq(booking)); + + } + + private Optional flight() { + return Optional.of(Flight.builder() + .flightNumber("Oceanic 815") + .airline("Oceanic") + .build()); + } + + private Booking booking() { + return Booking.builder() + .flightNumber("Oceanic 815") + .customer(customer().get()) + .build(); + } + + private Optional customer() { + return Optional.of(Customer.builder() + .id(42L) + .name("Hurley") + .build()); + } + +} \ No newline at end of file diff --git a/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/web/BookingControllerTest.java b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/web/BookingControllerTest.java new file mode 100644 index 0000000..ecb6a59 --- /dev/null +++ b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/booking/web/BookingControllerTest.java @@ -0,0 +1,67 @@ +package io.reflectoring.booking.web; + +import java.util.Arrays; + +import io.reflectoring.booking.business.BookingService; +import io.reflectoring.booking.data.Booking; +import io.reflectoring.customer.data.Customer; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@ExtendWith(SpringExtension.class) +@WebMvcTest(controllers = BookingController.class) +class BookingControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ApplicationContext applicationContext; + + @MockBean + private BookingService bookingService; + + @BeforeEach + void printApplicationContext() { + Arrays.stream(applicationContext.getBeanDefinitionNames()) + .map(name -> applicationContext.getBean(name).getClass().getName()) + .sorted() + .forEach(System.out::println); + } + + @Test + void bookFlightReturnsHttpStatusOk() throws Exception { + when(bookingService.bookFlight(eq(42L), eq("Oceanic 815"))) + .thenReturn(expectedBooking()); + + mockMvc.perform( + post("/booking") + .param("customerId", "42") + .param("flightNumber", "Oceanic 815")) + .andExpect(status().isOk()); + } + + private Booking expectedBooking() { + return Booking.builder() + .customer(Customer.builder() + .id(42L) + .name("Zaphod") + .build()) + .flightNumber("Oceanic 815") + .build(); + } + +} \ No newline at end of file diff --git a/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/customer/CustomerConfigurationTest.java b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/customer/CustomerConfigurationTest.java new file mode 100644 index 0000000..92c2539 --- /dev/null +++ b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/customer/CustomerConfigurationTest.java @@ -0,0 +1,16 @@ +package io.reflectoring.customer; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = CustomerConfiguration.class) +class CustomerConfigurationTest { + + @Test + void bookingConfigurationLoads() { + } + +} \ No newline at end of file diff --git a/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/customer/data/CustomerRepositoryTest.java b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/customer/data/CustomerRepositoryTest.java new file mode 100644 index 0000000..ec1e14e --- /dev/null +++ b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/customer/data/CustomerRepositoryTest.java @@ -0,0 +1,44 @@ +package io.reflectoring.customer.data; + +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(SpringExtension.class) +@DataJpaTest +class CustomerRepositoryTest { + + @Autowired + private CustomerRepository repository; + + @Autowired + private ApplicationContext applicationContext; + + @BeforeEach + void printApplicationContext() { + Arrays.stream(applicationContext.getBeanDefinitionNames()) + .map(name -> applicationContext.getBean(name).getClass().getName()) + .sorted() + .forEach(System.out::println); + } + + @Test + void findsByName() { + Customer customer = Customer.builder() + .name("Hurley") + .build(); + repository.save(customer); + + List foundCustomers = repository.findByName("Hurley"); + assertThat(foundCustomers).hasSize(1); + } + +} \ No newline at end of file diff --git a/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/flight/FlightMockConfiguration.java b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/flight/FlightMockConfiguration.java new file mode 100644 index 0000000..de4186d --- /dev/null +++ b/spring-boot/spring-boot-testing/src/test/java/io/reflectoring/flight/FlightMockConfiguration.java @@ -0,0 +1,4 @@ +package io.reflectoring.flight; + +public class FlightMockConfiguration { +} diff --git a/spring-cloud/spring-cloud-contract-consumer/src/test/java/io/reflectoring/UserClientTest.java b/spring-cloud/spring-cloud-contract-consumer/src/test/java/io/reflectoring/UserClientTest.java index 6c3b90a..4832059 100644 --- a/spring-cloud/spring-cloud-contract-consumer/src/test/java/io/reflectoring/UserClientTest.java +++ b/spring-cloud/spring-cloud-contract-consumer/src/test/java/io/reflectoring/UserClientTest.java @@ -12,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureStubRunner(ids = "io.reflectoring:user-service:+:stubs:6565", workOffline = true) -@Ignore("Cannot work on CI because workOffline is set to true.") +//@Ignore("Cannot work on CI because workOffline is set to true.") public class UserClientTest { @Autowired