Merge pull request #10 from wkrzywiec/add-new-book-event
Add new book event
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -131,6 +131,10 @@
|
||||
</executions>
|
||||
<configuration>
|
||||
<reportsDirectory>${surefire.and.failsafe.report.dir}</reportsDirectory>
|
||||
<includes>
|
||||
<include>**/*ITCase.java</include>
|
||||
<include>**/*ComponentTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package io.wkrzywiec.hexagonal.library.borrowing;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.TestData;
|
||||
import io.wkrzywiec.hexagonal.library.borrowing.model.BookReservationCommand;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.infrastructure.BookRepository;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class MakeReservationComponentTest {
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@Autowired
|
||||
private BookRepository bookRepository;
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
private String baseURL;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
this.baseURL = "http://localhost:" + port;
|
||||
|
||||
Book book = bookRepository.save(TestData.homoDeusBook());
|
||||
jdbcTemplate.update(
|
||||
"INSERT INTO available (book_id) VALUES (?)",
|
||||
book.getIdAsLong());
|
||||
|
||||
jdbcTemplate.update(
|
||||
"INSERT INTO user (first_name, last_name, email) VALUES (?, ?, ?)",
|
||||
"John",
|
||||
"Doe",
|
||||
"john.doe@test.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Reserve available book")
|
||||
public void givenBookIsAvailable_thenMakeReservation_thenBookIsReserved() {
|
||||
//given
|
||||
Long homoDeusBookId = jdbcTemplate.queryForObject(
|
||||
"SELECT id FROM book WHERE title = ?",
|
||||
Long.class,
|
||||
TestData.homoDeusBookTitle());
|
||||
|
||||
Long activeUserId = jdbcTemplate.queryForObject(
|
||||
"SELECT id FROM user WHERE email = ?",
|
||||
Long.class,
|
||||
"john.doe@test.com");
|
||||
|
||||
|
||||
BookReservationCommand reservationCommand =
|
||||
BookReservationCommand.builder()
|
||||
.bookId(homoDeusBookId )
|
||||
.userId(activeUserId)
|
||||
.build();
|
||||
|
||||
//when
|
||||
given()
|
||||
.contentType("application/json")
|
||||
.body(reservationCommand)
|
||||
.when()
|
||||
.post( baseURL + "/reservations")
|
||||
.prettyPeek()
|
||||
.then();
|
||||
|
||||
Long reservationId = jdbcTemplate.queryForObject(
|
||||
"SELECT id FROM reserved WHERE book_id = ?",
|
||||
Long.class,
|
||||
homoDeusBookId);
|
||||
|
||||
assertTrue(reservationId > 0);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import io.restassured.RestAssured;
|
||||
import io.restassured.response.ValidatableResponse;
|
||||
import io.wkrzywiec.hexagonal.library.TestData;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.AddNewBookCommand;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -12,16 +11,14 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import static io.restassured.RestAssured.given;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
public class AddNewBookTest {
|
||||
public class AddNewBookComponentTest {
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
@@ -55,8 +52,8 @@ public class AddNewBookTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Add new book to a database")
|
||||
public void givenGoogleBooId_whenAddNewBook_thenBookIsSaved(){
|
||||
@DisplayName("Add new book to a database & make it available")
|
||||
public void givenGoogleBooId_whenAddNewBook_thenBookIsSaved() {
|
||||
//given
|
||||
AddNewBookCommand addNewBookCommand =
|
||||
AddNewBookCommand.builder()
|
||||
@@ -77,6 +74,14 @@ public class AddNewBookTest {
|
||||
"SELECT id FROM book WHERE book_external_id = ?",
|
||||
Long.class,
|
||||
TestData.homoDeusBookGoogleId());
|
||||
|
||||
assertTrue(savedBookId > 0);
|
||||
|
||||
Long availableBookId = jdbc.queryForObject(
|
||||
"SELECT id FROM available WHERE book_id = ?",
|
||||
Long.class,
|
||||
savedBookId);
|
||||
|
||||
assertTrue(availableBookId > 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package io.wkrzywiec.hexagonal.library;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.borrowing.BorrowingFacade;
|
||||
import io.wkrzywiec.hexagonal.library.borrowing.infrastructure.BorrowingDatabaseAdapter;
|
||||
import io.wkrzywiec.hexagonal.library.borrowing.ports.incoming.MakeBookAvailable;
|
||||
import io.wkrzywiec.hexagonal.library.borrowing.ports.outgoing.BorrowingDatabase;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
@Configuration
|
||||
public class BorrowingDomainConfig {
|
||||
|
||||
@Bean
|
||||
public BorrowingDatabase borrowingDatabase(JdbcTemplate jdbcTemplate) {
|
||||
return new BorrowingDatabaseAdapter(jdbcTemplate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MakeBookAvailable makeBookAvailable(BorrowingDatabase database) {
|
||||
return new BorrowingFacade(database);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.wkrzywiec.hexagonal.library;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.inventory.InventoryFacade;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.infrastructure.BookRepository;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.infrastructure.GoogleBooksAdapter;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.infrastructure.InventoryDatabaseAdapter;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.infrastructure.SpringInventoryEventPublisherAdapter;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.incoming.AddNewBook;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
class InventoryDomainConfig {
|
||||
|
||||
@Bean
|
||||
SpringInventoryEventPublisherAdapter springInventoryEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
|
||||
return new SpringInventoryEventPublisherAdapter(applicationEventPublisher);
|
||||
}
|
||||
|
||||
@Bean
|
||||
AddNewBook addNewBook(BookRepository repository, RestTemplate restTemplate, ApplicationEventPublisher applicationEventPublisher){
|
||||
return new InventoryFacade(
|
||||
new InventoryDatabaseAdapter(repository),
|
||||
new GoogleBooksAdapter(restTemplate),
|
||||
springInventoryEventPublisher(applicationEventPublisher));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.wkrzywiec.hexagonal.library;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
public class LibraryHexagonalConfig {
|
||||
|
||||
@Bean
|
||||
RestTemplate restTemplate(){
|
||||
return new RestTemplate();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package io.wkrzywiec.hexagonal.library.borrowing.application;
|
||||
|
||||
public class BorrowingController {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.wkrzywiec.hexagonal.library.borrowing.application;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.borrowing.model.MakeBookAvailableCommand;
|
||||
import io.wkrzywiec.hexagonal.library.borrowing.ports.incoming.MakeBookAvailable;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.NewBookWasAddedEvent;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Component
|
||||
public class NewBookWasAddedEventHandler {
|
||||
|
||||
private final MakeBookAvailable makeBookAvailable;
|
||||
|
||||
@EventListener
|
||||
public void handle(NewBookWasAddedEvent event){
|
||||
makeBookAvailable.handle(new MakeBookAvailableCommand(event.getBookIdAsLong()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package io.wkrzywiec.hexagonal.library.borrowing.application;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.borrowing.model.BookReservationCommand;
|
||||
import io.wkrzywiec.hexagonal.library.borrowing.ports.incoming.ReserveBook;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/reservations")
|
||||
@RequiredArgsConstructor
|
||||
public class ReservationController {
|
||||
|
||||
private final ReserveBook reserveBook;
|
||||
|
||||
@PostMapping("")
|
||||
public ResponseEntity<String> makeReservation(@RequestBody BookReservationCommand reservationCommand){
|
||||
Long reservationId = reserveBook.handle(reservationCommand);
|
||||
return new ResponseEntity<>("Reservation has been made with an id " + reservationId, HttpStatus.CREATED);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@AllArgsConstructor
|
||||
class BorrowingDatabaseAdapter implements BorrowingDatabase {
|
||||
public class BorrowingDatabaseAdapter implements BorrowingDatabase {
|
||||
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
|
||||
@@ -2,23 +2,29 @@ package io.wkrzywiec.hexagonal.library.inventory;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.AddNewBookCommand;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.NewBookWasAddedEvent;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.incoming.AddNewBook;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryEventPublisher;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.GetBookDetails;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryDatabase;
|
||||
|
||||
|
||||
public class InventoryFacade implements AddNewBook{
|
||||
|
||||
private InventoryDatabase database;
|
||||
private GetBookDetails getBookDetails;
|
||||
private InventoryEventPublisher eventPublisher;
|
||||
|
||||
public InventoryFacade(InventoryDatabase database, GetBookDetails getBookDetails) {
|
||||
public InventoryFacade(InventoryDatabase database, GetBookDetails getBookDetails, InventoryEventPublisher eventPublisher) {
|
||||
this.database = database;
|
||||
this.getBookDetails = getBookDetails;
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(AddNewBookCommand addNewBookCommand){
|
||||
Book book = getBookDetails.handle(addNewBookCommand.getGoogleBookId());
|
||||
database.save(book);
|
||||
Book savedBook = database.save(book);
|
||||
eventPublisher.publishNewBookWasAddedEvent(new NewBookWasAddedEvent(savedBook.getIdAsLong()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
interface BookRepository extends CrudRepository<Book, Long> {
|
||||
public interface BookRepository extends CrudRepository<Book, Long> {
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.util.stream.StreamSupport;
|
||||
import static java.util.Optional.ofNullable;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
class GoogleBooksAdapter implements GetBookDetails {
|
||||
public class GoogleBooksAdapter implements GetBookDetails {
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
|
||||
@@ -5,12 +5,12 @@ import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryDatabase
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
class InventoryDatabaseAdapter implements InventoryDatabase {
|
||||
public class InventoryDatabaseAdapter implements InventoryDatabase {
|
||||
|
||||
private final BookRepository repository;
|
||||
|
||||
@Override
|
||||
public void save(Book book) {
|
||||
repository.save(book);
|
||||
public Book save(Book book) {
|
||||
return repository.save(book);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package io.wkrzywiec.hexagonal.library.inventory.infrastructure;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.inventory.InventoryFacade;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.incoming.AddNewBook;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@Configuration
|
||||
class InventoryDomainConfig {
|
||||
|
||||
@Bean
|
||||
RestTemplate restTemplate(){
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
@Bean
|
||||
AddNewBook addNewBook(BookRepository repository, RestTemplate restTemplate){
|
||||
return new InventoryFacade(
|
||||
new InventoryDatabaseAdapter(repository),
|
||||
new GoogleBooksAdapter(restTemplate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.wkrzywiec.hexagonal.library.inventory.infrastructure;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.NewBookWasAddedEvent;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryEventPublisher;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class SpringInventoryEventPublisherAdapter implements InventoryEventPublisher {
|
||||
|
||||
private final ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
@Override
|
||||
public void publishNewBookWasAddedEvent(NewBookWasAddedEvent event) {
|
||||
applicationEventPublisher.publishEvent(event);
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,10 @@ public class Book {
|
||||
this.imageLink = imageLink;
|
||||
}
|
||||
|
||||
public Long getIdAsLong(){
|
||||
return id;
|
||||
}
|
||||
|
||||
private Book() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.wkrzywiec.hexagonal.library.inventory.model;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class NewBookWasAddedEvent {
|
||||
|
||||
private final Long bookId;
|
||||
private final Instant timestamp;
|
||||
|
||||
public NewBookWasAddedEvent(Long bookId) {
|
||||
this.bookId = bookId;
|
||||
timestamp = Instant.now();
|
||||
}
|
||||
|
||||
public Long getBookIdAsLong() {
|
||||
return bookId;
|
||||
}
|
||||
|
||||
public String getEventTimeStampAsString() {
|
||||
return timestamp.toString();
|
||||
}
|
||||
}
|
||||
@@ -3,5 +3,5 @@ package io.wkrzywiec.hexagonal.library.inventory.ports.outgoing;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
|
||||
|
||||
public interface InventoryDatabase {
|
||||
void save(Book book);
|
||||
Book save(Book book);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package io.wkrzywiec.hexagonal.library.inventory.ports.outgoing;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.NewBookWasAddedEvent;
|
||||
|
||||
public interface InventoryEventPublisher {
|
||||
void publishNewBookWasAddedEvent(NewBookWasAddedEvent event);
|
||||
}
|
||||
@@ -5,22 +5,13 @@ import com.tngtech.archunit.junit.AnalyzeClasses;
|
||||
import com.tngtech.archunit.junit.ArchTest;
|
||||
import com.tngtech.archunit.lang.ArchRule;
|
||||
import io.wkrzywiec.hexagonal.library.borrowing.BorrowingFacade;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.InventoryFacade;
|
||||
|
||||
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClass;
|
||||
import static com.tngtech.archunit.library.Architectures.onionArchitecture;
|
||||
|
||||
@AnalyzeClasses(packages = {"io.wkrzywiec.hexagonal.library.inventory",
|
||||
"io.wkrzywiec.hexagonal.library.borrowing"},
|
||||
@AnalyzeClasses(packages = {"io.wkrzywiec.hexagonal.library.borrowing"},
|
||||
importOptions = { ImportOption.DoNotIncludeTests.class })
|
||||
public class HexagonalArchitectureTest {
|
||||
|
||||
@ArchTest
|
||||
public static final ArchRule hexagonalArchInInventoryDomain = onionArchitecture()
|
||||
.domainModels("io.wkrzywiec.hexagonal.library.inventory.model..")
|
||||
.domainServices("io.wkrzywiec.hexagonal.library.inventory..")
|
||||
.applicationServices("io.wkrzywiec.hexagonal.library.inventory.application..")
|
||||
.adapter("infrastructure", "io.wkrzywiec.hexagonal.library.inventory.infrastructure..");
|
||||
public class BorrowingArchitectureTest {
|
||||
|
||||
@ArchTest
|
||||
public static final ArchRule hexagonalArchInBorrowingDomain = onionArchitecture()
|
||||
@@ -29,13 +20,6 @@ public class HexagonalArchitectureTest {
|
||||
.applicationServices("io.wkrzywiec.hexagonal.library.borrowing.application..")
|
||||
.adapter("infrastructure", "io.wkrzywiec.hexagonal.library.borrowing.infrastructure..");
|
||||
|
||||
@ArchTest
|
||||
public static final ArchRule noSpringDependenciesInInventoryFacade =
|
||||
noClass(InventoryFacade.class)
|
||||
.should()
|
||||
.dependOnClassesThat()
|
||||
.resideInAPackage("org.springframework..");
|
||||
|
||||
@ArchTest
|
||||
public static final ArchRule noSpringDependenciesInBorrowingFacade =
|
||||
noClass(BorrowingFacade.class)
|
||||
@@ -0,0 +1,30 @@
|
||||
package io.wkrzywiec.hexagonal.library.architecture;
|
||||
|
||||
import com.tngtech.archunit.core.importer.ImportOption;
|
||||
import com.tngtech.archunit.junit.AnalyzeClasses;
|
||||
import com.tngtech.archunit.junit.ArchTest;
|
||||
import com.tngtech.archunit.lang.ArchRule;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.InventoryFacade;
|
||||
|
||||
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClass;
|
||||
import static com.tngtech.archunit.library.Architectures.onionArchitecture;
|
||||
|
||||
@AnalyzeClasses(packages = {"io.wkrzywiec.hexagonal.library.inventory"},
|
||||
importOptions = { ImportOption.DoNotIncludeTests.class })
|
||||
public class InventoryArchitectureTest {
|
||||
|
||||
@ArchTest
|
||||
public static final ArchRule hexagonalArchInInventoryDomain = onionArchitecture()
|
||||
.domainModels("io.wkrzywiec.hexagonal.library.inventory.model..")
|
||||
.domainServices("io.wkrzywiec.hexagonal.library.inventory..")
|
||||
.applicationServices("io.wkrzywiec.hexagonal.library.inventory.application..")
|
||||
.adapter("infrastructure", "io.wkrzywiec.hexagonal.library.inventory.infrastructure..");
|
||||
|
||||
@ArchTest
|
||||
public static final ArchRule noSpringDependenciesInInventoryFacade =
|
||||
noClass(InventoryFacade.class)
|
||||
.should()
|
||||
.dependOnClassesThat()
|
||||
.resideInAPackage("org.springframework..");
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package io.wkrzywiec.hexagonal.library.inventory;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryDatabase;
|
||||
import org.apache.commons.lang3.reflect.FieldUtils;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@@ -11,8 +12,15 @@ public class InMemoryInventoryDatabase implements InventoryDatabase {
|
||||
ConcurrentHashMap<Long, Book> books = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void save(Book book) {
|
||||
public Book save(Book book) {
|
||||
Long id = books.size() + 1L;
|
||||
|
||||
try {
|
||||
FieldUtils.writeField(book, "id", id, true);
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
books.put(id, book);
|
||||
return book;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package io.wkrzywiec.hexagonal.library.inventory;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.NewBookWasAddedEvent;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryEventPublisher;
|
||||
|
||||
public class InvenotryEventPublisherFake implements InventoryEventPublisher {
|
||||
|
||||
@Override
|
||||
public void publishNewBookWasAddedEvent(NewBookWasAddedEvent event) { }
|
||||
}
|
||||
@@ -4,30 +4,33 @@ import io.wkrzywiec.hexagonal.library.TestData;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.AddNewBookCommand;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.GetBookDetails;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.InventoryEventPublisher;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
|
||||
public class InventoryFacadeTest {
|
||||
|
||||
private GetBookDetails getBookDetails;
|
||||
private InMemoryInventoryDatabase database;
|
||||
private InventoryEventPublisher eventPublisher;
|
||||
private InventoryFacade facade;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
database = new InMemoryInventoryDatabase();
|
||||
getBookDetails = new GetBookDetailsFake();
|
||||
facade = new InventoryFacade(database, getBookDetails);
|
||||
eventPublisher = new InvenotryEventPublisherFake();
|
||||
facade = new InventoryFacade(database, getBookDetails, eventPublisher);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Correctly save a new book in a repository")
|
||||
public void correctlySaveBook(){
|
||||
//given
|
||||
Book expectedBook = TestData.homoDeusBook();
|
||||
AddNewBookCommand externalBookId = AddNewBookCommand
|
||||
.builder()
|
||||
.googleBookId(TestData.homoDeusBookGoogleId())
|
||||
@@ -38,6 +41,6 @@ public class InventoryFacadeTest {
|
||||
|
||||
//then
|
||||
Book actualBook = database.books.get(1L);
|
||||
assertEquals(expectedBook, actualBook);
|
||||
assertNotNull(actualBook);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package io.wkrzywiec.hexagonal.library.inventory.infrastructure;
|
||||
|
||||
import io.wkrzywiec.hexagonal.library.TestData;
|
||||
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@DataJpaTest
|
||||
public class InventoryDatabaseAdapterITCase {
|
||||
|
||||
@Autowired
|
||||
private BookRepository bookRepository;
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
private InventoryDatabaseAdapter database;
|
||||
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
database = new InventoryDatabaseAdapter(bookRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Save new book in database")
|
||||
public void givenBook_whenSaveIt_thenBookIsSaved() {
|
||||
//given
|
||||
Book homoDeusBook = TestData.homoDeusBook();
|
||||
|
||||
//when
|
||||
Book savedBook = database.save(homoDeusBook);
|
||||
|
||||
//then
|
||||
Long savedBookId = jdbcTemplate.queryForObject(
|
||||
"SELECT id FROM book WHERE id = ?",
|
||||
Long.class,
|
||||
savedBook.getIdAsLong());
|
||||
|
||||
assertEquals(savedBook.getIdAsLong(), savedBookId);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user