diff --git a/ddd/src/main/java/com/baeldung/hexagonal/HexagonalSpringApplication.java b/ddd/src/main/java/com/baeldung/hexagonal/HexagonalSpringApplication.java deleted file mode 100644 index c679d459f0..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/HexagonalSpringApplication.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.hexagonal; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; -import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration; -import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; - - -@SpringBootApplication(exclude={ - CassandraAutoConfiguration.class, - MongoDataAutoConfiguration.class, - MongoAutoConfiguration.class -}) -public class HexagonalSpringApplication { - - public static void main(final String[] args) { - SpringApplication.run(HexagonalSpringApplication.class, args); - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/adapter/BookingPersistenceAdapter.java b/ddd/src/main/java/com/baeldung/hexagonal/adapter/BookingPersistenceAdapter.java deleted file mode 100644 index 1b191bde86..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/adapter/BookingPersistenceAdapter.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.hexagonal.adapter; - -import com.baeldung.hexagonal.domain.Booking; -import com.baeldung.hexagonal.port.BookingPersistencePort; -import com.baeldung.hexagonal.repository.BookingRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -@Component -public class BookingPersistenceAdapter implements BookingPersistencePort { - - @Autowired - private BookingRepository bookingRepository; - - public boolean persist(Booking booking) { - return bookingRepository.save(booking); - } - - public boolean updateStatus(String bookingId, String status) { - return bookingRepository.updateStatus(bookingId, status); - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/adapter/RestAPIEndpointAdapter.java b/ddd/src/main/java/com/baeldung/hexagonal/adapter/RestAPIEndpointAdapter.java deleted file mode 100644 index 3e1b1fc90f..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/adapter/RestAPIEndpointAdapter.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.hexagonal.adapter; - -import com.baeldung.hexagonal.port.BookingServicePort; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; - -import static com.baeldung.hexagonal.port.BookingServicePort.BookingRequest; -import static com.baeldung.hexagonal.port.BookingServicePort.BookingResponse; -import static com.baeldung.hexagonal.port.BookingServicePort.BookingResponse.SUCCESS; -import static org.springframework.http.HttpStatus.CREATED; -import static org.springframework.http.HttpStatus.FAILED_DEPENDENCY; - -@RestController -public class RestAPIEndpointAdapter { - - private BookingServicePort bookingServicePort; - - @Autowired - public RestAPIEndpointAdapter(BookingServicePort bookingServicePort) { - this.bookingServicePort = bookingServicePort; - } - - @PostMapping(path = "/booking") - public ResponseEntity createBooking(@RequestBody BookingRequest request) { - BookingResponse response = bookingServicePort.book(request); - return new ResponseEntity<>(response, - response.getStatusCode() == SUCCESS ? CREATED : FAILED_DEPENDENCY); - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/adapter/TheatreServiceAdapter.java b/ddd/src/main/java/com/baeldung/hexagonal/adapter/TheatreServiceAdapter.java deleted file mode 100644 index fa19483b13..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/adapter/TheatreServiceAdapter.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.hexagonal.adapter; - -import com.baeldung.hexagonal.external.service.TheatreService; -import com.baeldung.hexagonal.port.TheatreServicePort; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; - -import java.util.Optional; -import java.util.Set; - -import static com.baeldung.hexagonal.external.service.TheatreService.Reservation; -import static org.springframework.http.HttpStatus.CREATED; -import static org.springframework.http.HttpStatus.NO_CONTENT; - -@Component -public class TheatreServiceAdapter implements TheatreServicePort { - - @Autowired - private TheatreService theatreService; - - public Optional reserveSeats(String movieShowId, Set seats) { - ResponseEntity response = theatreService.postReservation(movieShowId, seats); - return response.getStatusCode() == CREATED ? Optional.of(response.getBody().getId()): Optional.empty(); - } - - public boolean releaseSeats(String resrevationId) { - return theatreService.deleteReservation(resrevationId).getStatusCode() == NO_CONTENT; - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/adapter/WalletServiceAdapter.java b/ddd/src/main/java/com/baeldung/hexagonal/adapter/WalletServiceAdapter.java deleted file mode 100644 index 1d8db867b7..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/adapter/WalletServiceAdapter.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.hexagonal.adapter; - -import com.baeldung.hexagonal.external.service.CustomerWalletService; -import com.baeldung.hexagonal.port.WalletServicePort; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import static org.springframework.http.HttpStatus.CREATED; - -@Component -public class WalletServiceAdapter implements WalletServicePort { - - @Autowired - private CustomerWalletService customerWalletService; - - public boolean debit(String customerId, Double amount) { - return customerWalletService.postDebit(customerId, amount) == CREATED; - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/domain/Booking.java b/ddd/src/main/java/com/baeldung/hexagonal/domain/Booking.java deleted file mode 100644 index ed9b7281f2..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/domain/Booking.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.baeldung.hexagonal.domain; - -import com.baeldung.hexagonal.port.BookingServicePort; - -import java.util.Set; -import java.util.UUID; - -public class Booking { - - public static final String STATUS_INITIAL = "INITIAL"; - public static final String STATUS_SUCCESS = "SUCCESS"; - public static final String STATUS_FAILURE = "FAILED"; - - private String bookingId; - private String movieShowId; - private String customerId; - private Set seats; - private Double amount; - private String status; - - public Booking( - String bookingId, String movieShowId, String customerId, Set seats, Double amount, String status) { - this.bookingId = bookingId; - this.movieShowId = movieShowId; - this.customerId = customerId; - this.seats = seats; - this.amount = amount; - this.status = status; - } - - public Booking(BookingServicePort.BookingRequest request) { - this.bookingId = UUID.randomUUID().toString(); - this.movieShowId = request.getMovieShowId(); - this.customerId = request.getCustomerId(); - this.seats = request.getSeats(); - this.amount = request.getAmount(); - this.status = STATUS_INITIAL; - } - - public String getMovieShowId() { - return movieShowId; - } - - public Set getSeats() { - return seats; - } - - public String getCustomerId() { - return customerId; - } - - public String getBookingId() { - return bookingId; - } - - public Double getAmount() { - return amount; - } - - public String getStatus() { - return status; - } - - public void setBookingId(String bookingId) { - this.bookingId = bookingId; - } - - public void setMovieShowId(String movieShowId) { - this.movieShowId = movieShowId; - } - - public void setCustomerId(String customerId) { - this.customerId = customerId; - } - - public void setSeats(Set seats) { - this.seats = seats; - } - - public void setAmount(Double amount) { - this.amount = amount; - } - - public void setStatus(String status) { - this.status = status; - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/external/service/CustomerWalletService.java b/ddd/src/main/java/com/baeldung/hexagonal/external/service/CustomerWalletService.java deleted file mode 100644 index 102cef788e..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/external/service/CustomerWalletService.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.hexagonal.external.service; - -import org.springframework.http.HttpStatus; - -public interface CustomerWalletService { - - HttpStatus postDebit(String customerId, Double amount); -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/external/service/MockCustomerWalletService.java b/ddd/src/main/java/com/baeldung/hexagonal/external/service/MockCustomerWalletService.java deleted file mode 100644 index 4a76368b19..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/external/service/MockCustomerWalletService.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.hexagonal.external.service; - -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Service; - -@Service -public class MockCustomerWalletService implements CustomerWalletService { - public HttpStatus postDebit(String customerId, Double amount) { - return HttpStatus.CREATED; - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/external/service/MockTheatreService.java b/ddd/src/main/java/com/baeldung/hexagonal/external/service/MockTheatreService.java deleted file mode 100644 index eb018e69b2..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/external/service/MockTheatreService.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.hexagonal.external.service; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Service; - -import java.util.Set; -import java.util.UUID; - -@Service -public class MockTheatreService implements TheatreService { - - public ResponseEntity postReservation(String movieShowId, Set seats) { - return new ResponseEntity<>( - new Reservation(UUID.randomUUID().toString()), HttpStatus.CREATED); - } - - public ResponseEntity deleteReservation(String reservationId) { - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/external/service/TheatreService.java b/ddd/src/main/java/com/baeldung/hexagonal/external/service/TheatreService.java deleted file mode 100644 index 8107bfb418..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/external/service/TheatreService.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.hexagonal.external.service; - -import org.springframework.http.ResponseEntity; - -import java.util.Set; - -public interface TheatreService { - - ResponseEntity postReservation(String movieShowId, Set seats); - - ResponseEntity deleteReservation(String reservationId); - - class Reservation { - private final String id; - - public Reservation(String id) { - this.id = id; - } - - public String getId() { - return id; - } - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/port/BookingPersistencePort.java b/ddd/src/main/java/com/baeldung/hexagonal/port/BookingPersistencePort.java deleted file mode 100644 index c1d1d73630..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/port/BookingPersistencePort.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.hexagonal.port; - -import com.baeldung.hexagonal.domain.Booking; - -public interface BookingPersistencePort { - boolean persist(Booking booking); - public boolean updateStatus(String bookingId, String status); -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/port/BookingServicePort.java b/ddd/src/main/java/com/baeldung/hexagonal/port/BookingServicePort.java deleted file mode 100644 index 12710a6014..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/port/BookingServicePort.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.baeldung.hexagonal.port; - -import java.util.Set; - -public interface BookingServicePort { - - BookingResponse book(BookingRequest request); - - class BookingRequest { - private String movieShowId; - private String customerId; - private Set seats; - private Double amount; - - public String getMovieShowId() { - return movieShowId; - } - - public void setMovieShowId(String movieShowId) { - this.movieShowId = movieShowId; - } - - public String getCustomerId() { - return customerId; - } - - public void setCustomerId(String customerId) { - this.customerId = customerId; - } - - public Set getSeats() { - return seats; - } - - public void setSeats(Set seats) { - this.seats = seats; - } - - public Double getAmount() { - return amount; - } - - public void setAmount(Double amount) { - this.amount = amount; - } - } - - class BookingResponse { - public static final int SUCCESS = 0; - public static final int SEAT_NOT_AVAILABLE = 1; - public static final int PAYMENT_FAILED = 2; - public static final int UNKNOWN_ERROR = 3; - - private final int statusCode; - private String bookingId; - - public BookingResponse(String bookingId, int statusCode) { - this.bookingId = bookingId; - this.statusCode = statusCode; - } - - public BookingResponse(int statusCode) { - this.statusCode = statusCode; - } - - public int getStatusCode() { - return statusCode; - } - public String getBookingId() { - return bookingId; - } - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/port/TheatreServicePort.java b/ddd/src/main/java/com/baeldung/hexagonal/port/TheatreServicePort.java deleted file mode 100644 index 8e5fab8b46..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/port/TheatreServicePort.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.hexagonal.port; - -import java.util.Optional; -import java.util.Set; - -public interface TheatreServicePort { - Optional reserveSeats(String movieShowId, Set seats); - boolean releaseSeats(String resrevationId); -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/port/WalletServicePort.java b/ddd/src/main/java/com/baeldung/hexagonal/port/WalletServicePort.java deleted file mode 100644 index 102bb619e8..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/port/WalletServicePort.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.hexagonal.port; - -public interface WalletServicePort { - boolean debit(String customerId, Double amount); -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/repository/BookingRepository.java b/ddd/src/main/java/com/baeldung/hexagonal/repository/BookingRepository.java deleted file mode 100644 index 7dd20290ba..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/repository/BookingRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.hexagonal.repository; - -import com.baeldung.hexagonal.domain.Booking; - -public interface BookingRepository { - - boolean save(Booking booking); - boolean updateStatus(String bookingId, String status); -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/repository/MockBookingRepository.java b/ddd/src/main/java/com/baeldung/hexagonal/repository/MockBookingRepository.java deleted file mode 100644 index 1738e606d0..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/repository/MockBookingRepository.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.hexagonal.repository; - -import com.baeldung.hexagonal.domain.Booking; -import org.springframework.stereotype.Repository; - -@Repository -public class MockBookingRepository implements BookingRepository { - public boolean save(Booking booking) { - return true; - } - - @Override - public boolean updateStatus(String bookingId, String status) { - return true; - } -} diff --git a/ddd/src/main/java/com/baeldung/hexagonal/usecase/BookTicketUseCase.java b/ddd/src/main/java/com/baeldung/hexagonal/usecase/BookTicketUseCase.java deleted file mode 100644 index 8d3112bd37..0000000000 --- a/ddd/src/main/java/com/baeldung/hexagonal/usecase/BookTicketUseCase.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.baeldung.hexagonal.usecase; - -import com.baeldung.hexagonal.domain.Booking; -import com.baeldung.hexagonal.port.BookingPersistencePort; -import com.baeldung.hexagonal.port.BookingServicePort; -import com.baeldung.hexagonal.port.TheatreServicePort; -import com.baeldung.hexagonal.port.WalletServicePort; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.util.Optional; - -import static com.baeldung.hexagonal.domain.Booking.STATUS_FAILURE; -import static com.baeldung.hexagonal.domain.Booking.STATUS_SUCCESS; -import static com.baeldung.hexagonal.port.BookingServicePort.BookingResponse.*; - -@Component -public class BookTicketUseCase implements BookingServicePort { - - private BookingPersistencePort bookingPersistencePort; - private TheatreServicePort theatreServicePort; - private WalletServicePort walletServicePort; - - @Autowired - public BookTicketUseCase(BookingPersistencePort bookingPersistencePort, TheatreServicePort theatreServicePort, WalletServicePort walletServicePort) { - this.bookingPersistencePort = bookingPersistencePort; - this.theatreServicePort = theatreServicePort; - this.walletServicePort = walletServicePort; - } - - public BookingResponse book(BookingRequest request) { - - Booking booking = new Booking(request); - - if (!bookingPersistencePort.persist(booking)) { - return new BookingResponse(UNKNOWN_ERROR); - } - - String bookingId = booking.getBookingId(); - - Optional reservationIdOptional = theatreServicePort.reserveSeats(booking.getMovieShowId(), booking.getSeats()); - if (!reservationIdOptional.isPresent()) { - bookingPersistencePort.updateStatus(bookingId, STATUS_FAILURE); - return new BookingResponse(bookingId, SEAT_NOT_AVAILABLE); - } - - if (!walletServicePort.debit(booking.getCustomerId(), booking.getAmount())) { - reservationIdOptional.ifPresent(reservationId -> theatreServicePort.releaseSeats(reservationId)); - bookingPersistencePort.updateStatus(bookingId, STATUS_FAILURE); - return new BookingResponse(bookingId, PAYMENT_FAILED); - } - - bookingPersistencePort.updateStatus(bookingId, STATUS_SUCCESS); - - return new BookingResponse(bookingId, SUCCESS); - } -} diff --git a/ddd/src/test/java/com/baeldung/hexagonal/adapter/RestAPIEndpointAdapterUnitTest.java b/ddd/src/test/java/com/baeldung/hexagonal/adapter/RestAPIEndpointAdapterUnitTest.java deleted file mode 100644 index cb22f5f37a..0000000000 --- a/ddd/src/test/java/com/baeldung/hexagonal/adapter/RestAPIEndpointAdapterUnitTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.baeldung.hexagonal.adapter; - -import com.baeldung.hexagonal.port.BookingServicePort; -import com.baeldung.hexagonal.port.BookingServicePort.BookingRequest; -import com.baeldung.hexagonal.port.BookingServicePort.BookingResponse; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; - -import java.util.Arrays; -import java.util.HashSet; - -import static com.baeldung.hexagonal.port.BookingServicePort.BookingResponse.*; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - -class RestAPIEndpointAdapterUnitTest { - - private BookingServicePort bookingServicePort; - private RestAPIEndpointAdapter restAPIEndpointAdapter; - - @BeforeEach - void setUp() { - bookingServicePort = mock(BookingServicePort.class); - restAPIEndpointAdapter = new RestAPIEndpointAdapter(bookingServicePort); - } - - private BookingServicePort.BookingRequest getBookingRequest() { - BookingServicePort.BookingRequest request = new BookingServicePort.BookingRequest(); - request.setMovieShowId("movie-show-id"); - request.setCustomerId("customer-id"); - request.setSeats(new HashSet<>(Arrays.asList("A1", "A2"))); - request.setAmount(100.00); - return request; - } - - @Test - void whenBookingServicePortReturnsUnknownError_thenReturnInternalServerError() { - BookingServicePort.BookingRequest request = getBookingRequest(); - when(bookingServicePort.book(any(BookingRequest.class))).thenReturn(new BookingResponse(UNKNOWN_ERROR)); - - ResponseEntity response = restAPIEndpointAdapter.createBooking(request); - - verify(bookingServicePort).book(any(BookingRequest.class)); - assertNotNull(response); - assertEquals(HttpStatus.FAILED_DEPENDENCY, response.getStatusCode()); - } - - @Test - void whenBookingServicePortReturnsSeatUnavailable_thenReturnPreconditionFailed() { - BookingServicePort.BookingRequest request = getBookingRequest(); - when(bookingServicePort.book(any(BookingRequest.class))).thenReturn(new BookingResponse(SEAT_NOT_AVAILABLE)); - - ResponseEntity response = restAPIEndpointAdapter.createBooking(request); - - verify(bookingServicePort).book(any(BookingRequest.class)); - assertNotNull(response); - assertEquals(HttpStatus.FAILED_DEPENDENCY, response.getStatusCode()); - } - - @Test - void whenBookingServicePortReturnsPaymentFailed_thenReturnPreconditionFailed() { - BookingServicePort.BookingRequest request = getBookingRequest(); - when(bookingServicePort.book(any(BookingRequest.class))).thenReturn(new BookingResponse(PAYMENT_FAILED)); - - ResponseEntity response = restAPIEndpointAdapter.createBooking(request); - - verify(bookingServicePort).book(any(BookingRequest.class)); - assertNotNull(response); - assertEquals(HttpStatus.FAILED_DEPENDENCY, response.getStatusCode()); - } - - @Test - void whenBookingServicePortReturnsSuccess_thenReturnCreated() { - BookingServicePort.BookingRequest request = getBookingRequest(); - when(bookingServicePort.book(any(BookingRequest.class))).thenReturn(new BookingResponse(SUCCESS)); - - ResponseEntity response = restAPIEndpointAdapter.createBooking(request); - - verify(bookingServicePort).book(any(BookingRequest.class)); - assertNotNull(response); - assertEquals(HttpStatus.CREATED, response.getStatusCode()); - } -} \ No newline at end of file diff --git a/ddd/src/test/java/com/baeldung/hexagonal/usecase/BookTicketUseCaseUnitTest.java b/ddd/src/test/java/com/baeldung/hexagonal/usecase/BookTicketUseCaseUnitTest.java deleted file mode 100644 index ffb4246f79..0000000000 --- a/ddd/src/test/java/com/baeldung/hexagonal/usecase/BookTicketUseCaseUnitTest.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.baeldung.hexagonal.usecase; - -import com.baeldung.hexagonal.domain.Booking; -import com.baeldung.hexagonal.port.BookingPersistencePort; -import com.baeldung.hexagonal.port.BookingServicePort; -import com.baeldung.hexagonal.port.TheatreServicePort; -import com.baeldung.hexagonal.port.WalletServicePort; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - -class BookTicketUseCaseUnitTest { - - private BookingPersistencePort bookingPersistencePort; - private TheatreServicePort theatreServicePort; - private WalletServicePort walletServicePort; - private BookTicketUseCase bookTicketUseCase; - - @BeforeEach - void setUp() { - bookingPersistencePort = mock(BookingPersistencePort.class); - theatreServicePort = mock(TheatreServicePort.class); - walletServicePort = mock(WalletServicePort.class); - bookTicketUseCase = new BookTicketUseCase(bookingPersistencePort, theatreServicePort, walletServicePort); - } - - private BookingServicePort.BookingRequest getBookingRequest() { - BookingServicePort.BookingRequest request = new BookingServicePort.BookingRequest(); - request.setMovieShowId("movie-show-id"); - request.setCustomerId("customer-id"); - request.setSeats(new HashSet<>(Arrays.asList("A1", "A2"))); - request.setAmount(100.00); - return request; - } - - @Test - void whenErrorInInitialPersistence_thenReturnUnknownError() { - BookingServicePort.BookingRequest request = getBookingRequest(); - Booking booking = new Booking(request); - when(bookingPersistencePort.persist(any(Booking.class))).thenReturn(false); - BookingServicePort.BookingResponse response = bookTicketUseCase.book(request); - - verify(bookingPersistencePort, times(1)).persist(any(Booking.class)); - assertNotNull(response); - assertEquals(BookingServicePort.BookingResponse.UNKNOWN_ERROR, response.getStatusCode()); - } - - @Test - void whenErrorInReserveSeats_thenReturnSeatNotAvailable() { - BookingServicePort.BookingRequest request = getBookingRequest(); - Booking booking = new Booking(request); - when(bookingPersistencePort.persist(any(Booking.class))).thenReturn(true); - when(theatreServicePort.reserveSeats(booking.getMovieShowId(), booking.getSeats())) - .thenReturn(Optional.empty()); - BookingServicePort.BookingResponse response = bookTicketUseCase.book(request); - - verify(bookingPersistencePort).persist(any(Booking.class)); - verify(bookingPersistencePort).updateStatus(any(String.class), any(String.class)); - verify(theatreServicePort).reserveSeats(any(String.class), any(HashSet.class)); - assertNotNull(response); - assertEquals(BookingServicePort.BookingResponse.SEAT_NOT_AVAILABLE, response.getStatusCode()); - } - - @Test - void whenErrorInWalletDebit_thenReturnPaymentFailed() { - BookingServicePort.BookingRequest request = getBookingRequest(); - Booking booking = new Booking(request); - when(bookingPersistencePort.persist(any(Booking.class))).thenReturn(true); - when(theatreServicePort.reserveSeats(booking.getMovieShowId(), booking.getSeats())) - .thenReturn(Optional.of("reservation-id")); - when(walletServicePort.debit(booking.getCustomerId(), booking.getAmount())) - .thenReturn(false); - BookingServicePort.BookingResponse response = bookTicketUseCase.book(request); - - verify(bookingPersistencePort).persist(any(Booking.class)); - verify(bookingPersistencePort).updateStatus(any(String.class), any(String.class)); - verify(theatreServicePort).reserveSeats(any(String.class), any(HashSet.class)); - verify(walletServicePort).debit(any(String.class), any(Double.class)); - verify(theatreServicePort).releaseSeats(any(String.class)); - assertNotNull(response); - assertEquals(BookingServicePort.BookingResponse.PAYMENT_FAILED, response.getStatusCode()); - } - - @Test - void whenNoErrorInAnyPorts_thenReturnSuccess() { - BookingServicePort.BookingRequest request = getBookingRequest(); - Booking booking = new Booking(request); - when(bookingPersistencePort.persist(any(Booking.class))).thenReturn(true); - when(theatreServicePort.reserveSeats(booking.getMovieShowId(), booking.getSeats())) - .thenReturn(Optional.of("reservation-id")); - when(walletServicePort.debit(booking.getCustomerId(), booking.getAmount())) - .thenReturn(true); - BookingServicePort.BookingResponse response = bookTicketUseCase.book(request); - - verify(bookingPersistencePort).persist(any(Booking.class)); - verify(bookingPersistencePort).updateStatus(any(String.class), any(String.class)); - verify(theatreServicePort).reserveSeats( any(String.class), any(HashSet.class)); - verify(walletServicePort).debit(any(String.class), any(Double.class)); - assertNotNull(response); - assertEquals(BookingServicePort.BookingResponse.SUCCESS, response.getStatusCode()); - } -} \ No newline at end of file