Compare commits

...

5 Commits

Author SHA1 Message Date
wkrzywiec
4d69df25e9 UserTestData and BookTestData 2020-05-29 17:40:47 +02:00
wkrzywiec
fa0e83ad92 UserCommandController 2020-05-29 08:56:16 +02:00
wkrzywiec
93f2eed4c8 UserDatabaseAdapter implemented 2020-05-28 20:20:45 +02:00
wkrzywiec
b2b1003b0b add user domain 2020-05-28 13:24:33 +02:00
Wojtek Krzywiec
29f3997a98 Merge pull request #12 from wkrzywiec/reservation-email
Reservation email
2020-05-28 11:52:54 +02:00
33 changed files with 505 additions and 38 deletions

View File

@@ -23,6 +23,7 @@
**/io/wkrzywiec/hexagonal/library/borrowing/model/**,
**/io/wkrzywiec/hexagonal/library/email/model/**,
**/io/wkrzywiec/hexagonal/library/inventory/model/**,
**/io/wkrzywiec/hexagonal/library/user/model/**,
**/io/wkrzywiec/hexagonal/library/infrastructure/repository/*Entity.java
</code.coverage.exclusions>
</properties>

View File

@@ -1,7 +1,7 @@
package io.wkrzywiec.hexagonal.library.borrowing;
import io.restassured.RestAssured;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.BookTestData;
import io.wkrzywiec.hexagonal.library.borrowing.model.BookReservationCommand;
import io.wkrzywiec.hexagonal.library.inventory.infrastructure.BookRepository;
import org.junit.jupiter.api.BeforeEach;
@@ -46,7 +46,7 @@ public class MakeReservationComponentTest {
Long homoDeusBookId = jdbcTemplate.queryForObject(
"SELECT id FROM book WHERE title = ?",
Long.class,
TestData.homoDeusBookTitle());
BookTestData.homoDeusBookTitle());
Long activeUserId = jdbcTemplate.queryForObject(
"SELECT id FROM user WHERE email = ?",

View File

@@ -2,7 +2,7 @@ package io.wkrzywiec.hexagonal.library.inventory;
import io.restassured.RestAssured;
import io.restassured.response.ValidatableResponse;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.BookTestData;
import io.wkrzywiec.hexagonal.library.inventory.model.AddNewBookCommand;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
@@ -60,7 +60,7 @@ public class AddNewBookComponentTest {
//given
AddNewBookCommand addNewBookCommand =
AddNewBookCommand.builder()
.googleBookId(TestData.homoDeusBookGoogleId())
.googleBookId(BookTestData.homoDeusBookGoogleId())
.build();
//when
@@ -76,7 +76,7 @@ public class AddNewBookComponentTest {
Long savedBookId = jdbc.queryForObject(
"SELECT id FROM book WHERE book_external_id = ?",
Long.class,
TestData.homoDeusBookGoogleId());
BookTestData.homoDeusBookGoogleId());
assertTrue(savedBookId > 0);

View File

@@ -0,0 +1,64 @@
package io.wkrzywiec.hexagonal.library.user;
import io.restassured.RestAssured;
import io.wkrzywiec.hexagonal.library.user.model.AddUserCommand;
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 org.springframework.test.context.jdbc.Sql;
import static io.restassured.RestAssured.given;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AddNewUserComponentTest {
@LocalServerPort
private int port;
private String baseURL;
@Autowired
private JdbcTemplate jdbcTemplate;
@BeforeEach
public void init(){
baseURL = "http://localhost:" + port;
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
}
@Test
@DisplayName("Create new user")
@Sql(scripts = "/clean-database.sql", executionPhase = AFTER_TEST_METHOD)
public void shouldCreateNewUser(){
//given
AddUserCommand addUserCommand = AddUserCommand.builder()
.firstName("John")
.lastName("Doe")
.email("john.doe@test.com")
.build();
//when
given()
.contentType("application/json")
.body(addUserCommand)
.when()
.post( baseURL + "/users")
.prettyPeek()
.then();
//then
Long savedUserId = jdbcTemplate.queryForObject(
"SELECT id FROM user WHERE email = ?",
Long.class,
"john.doe@test.com");
assertTrue(savedUserId > 0);
}
}

View File

@@ -9,7 +9,8 @@ import org.springframework.context.annotation.Import;
LibraryHexagonalConfig.class,
InventoryDomainConfig.class,
BorrowingDomainConfig.class,
EmailDomainConfig.class
EmailDomainConfig.class,
UserDomainConfig.class
})
public class LibraryHexagonalApplication {

View File

@@ -0,0 +1,21 @@
package io.wkrzywiec.hexagonal.library;
import io.wkrzywiec.hexagonal.library.user.UserFacade;
import io.wkrzywiec.hexagonal.library.user.infrastructure.UserDatabaseAdapter;
import io.wkrzywiec.hexagonal.library.user.infrastructure.UserRepository;
import io.wkrzywiec.hexagonal.library.user.ports.incoming.AddNewUser;
import io.wkrzywiec.hexagonal.library.user.ports.outgoing.UserDatabase;
import org.springframework.context.annotation.Bean;
public class UserDomainConfig {
@Bean
public UserDatabase userDatabase(UserRepository userRepository){
return new UserDatabaseAdapter(userRepository);
}
@Bean
public AddNewUser addNewUser(UserDatabase userDatabase){
return new UserFacade(userDatabase);
}
}

View File

@@ -0,0 +1,4 @@
package io.wkrzywiec.hexagonal.library.borrowing.ports.incoming;
public interface BorrowBook {
}

View File

@@ -0,0 +1,4 @@
package io.wkrzywiec.hexagonal.library.borrowing.ports.incoming;
public interface CancelReservation {
}

View File

@@ -0,0 +1,4 @@
package io.wkrzywiec.hexagonal.library.borrowing.ports.incoming;
public interface GiveBackBook {
}

View File

@@ -0,0 +1,25 @@
package io.wkrzywiec.hexagonal.library.user;
import io.wkrzywiec.hexagonal.library.user.model.AddUserCommand;
import io.wkrzywiec.hexagonal.library.user.model.EmailAddress;
import io.wkrzywiec.hexagonal.library.user.model.User;
import io.wkrzywiec.hexagonal.library.user.model.UserIdentifier;
import io.wkrzywiec.hexagonal.library.user.ports.incoming.AddNewUser;
import io.wkrzywiec.hexagonal.library.user.ports.outgoing.UserDatabase;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public class UserFacade implements AddNewUser {
private final UserDatabase database;
@Override
public UserIdentifier handle(AddUserCommand addUserCommand) {
User user = new User(
new EmailAddress(addUserCommand.getEmail()),
addUserCommand.getFirstName(),
addUserCommand.getLastName()
);
return database.save(user);
}
}

View File

@@ -0,0 +1,25 @@
package io.wkrzywiec.hexagonal.library.user.application;
import io.wkrzywiec.hexagonal.library.user.model.AddUserCommand;
import io.wkrzywiec.hexagonal.library.user.ports.incoming.AddNewUser;
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("/users")
@RequiredArgsConstructor
public class UserCommandController {
private final AddNewUser addNewUser;
@PostMapping("")
public ResponseEntity<String> addNewUser(@RequestBody AddUserCommand addUserCommand){
addNewUser.handle(addUserCommand);
return new ResponseEntity<>("New user was added to library", HttpStatus.CREATED);
}
}

View File

@@ -0,0 +1,18 @@
package io.wkrzywiec.hexagonal.library.user.infrastructure;
import io.wkrzywiec.hexagonal.library.user.model.User;
import io.wkrzywiec.hexagonal.library.user.model.UserIdentifier;
import io.wkrzywiec.hexagonal.library.user.ports.outgoing.UserDatabase;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class UserDatabaseAdapter implements UserDatabase {
private final UserRepository userRepository;
@Override
public UserIdentifier save(User user) {
User savedUser = userRepository.save(user);
return new UserIdentifier(savedUser.getIdentifierAsLong());
}
}

View File

@@ -0,0 +1,9 @@
package io.wkrzywiec.hexagonal.library.user.infrastructure;
import io.wkrzywiec.hexagonal.library.user.model.User;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends CrudRepository<User, Long> {
}

View File

@@ -0,0 +1,17 @@
package io.wkrzywiec.hexagonal.library.user.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class AddUserCommand {
private String email;
private String firstName;
private String lastName;
}

View File

@@ -0,0 +1,28 @@
package io.wkrzywiec.hexagonal.library.user.model;
import lombok.EqualsAndHashCode;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@Embeddable
@EqualsAndHashCode
public class EmailAddress {
@Column(name="email")
private String value;
public EmailAddress(String value) {
Pattern pattern = Pattern.compile("^(.+)@(.+)$");
Matcher matcher = pattern.matcher(value);
if(matcher.matches()){
this.value = value;
} else {
throw new IllegalArgumentException("Provided value is not an email address");
}
}
private EmailAddress(){}
}

View File

@@ -0,0 +1,44 @@
package io.wkrzywiec.hexagonal.library.user.model;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="user")
@EqualsAndHashCode
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@EqualsAndHashCode.Exclude
private Long id;
@Embedded
private EmailAddress emailAddress;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
public User(EmailAddress emailAddress, String firstName, String lastName) {
this.emailAddress = emailAddress;
this.firstName = firstName;
this.lastName = lastName;
}
public Long getIdentifierAsLong(){
return id;
}
private User(){}
}

View File

@@ -0,0 +1,15 @@
package io.wkrzywiec.hexagonal.library.user.model;
public class UserIdentifier {
private final Long id;
public UserIdentifier(Long id) {
this.id = id;
}
public Long getAsLong(){
return id;
}
}

View File

@@ -0,0 +1,8 @@
package io.wkrzywiec.hexagonal.library.user.ports.incoming;
import io.wkrzywiec.hexagonal.library.user.model.AddUserCommand;
import io.wkrzywiec.hexagonal.library.user.model.UserIdentifier;
public interface AddNewUser {
UserIdentifier handle(AddUserCommand addUserCommand);
}

View File

@@ -0,0 +1,8 @@
package io.wkrzywiec.hexagonal.library.user.ports.outgoing;
import io.wkrzywiec.hexagonal.library.user.model.User;
import io.wkrzywiec.hexagonal.library.user.model.UserIdentifier;
public interface UserDatabase {
UserIdentifier save(User user);
}

View File

@@ -8,7 +8,7 @@ import io.wkrzywiec.hexagonal.library.inventory.model.Isbn13;
import java.util.Collections;
public class TestData {
public class BookTestData {
public static String homoDeusBookGoogleId() {
return "dWYyCwAAQBAJ";

View File

@@ -0,0 +1,8 @@
package io.wkrzywiec.hexagonal.library;
public class UserTestData {
public static String johnDoeEmail(){
return "john.doe@test.com";
}
}

View File

@@ -0,0 +1,29 @@
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.user.UserFacade;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClass;
import static com.tngtech.archunit.library.Architectures.onionArchitecture;
@AnalyzeClasses(packages = {"io.wkrzywiec.hexagonal.library.user"},
importOptions = { ImportOption.DoNotIncludeTests.class })
public class UserArchitectureTest {
@ArchTest
public static final ArchRule hexagonalArchInUserDomain = onionArchitecture()
.domainModels("io.wkrzywiec.hexagonal.library.user.model..")
.domainServices("io.wkrzywiec.hexagonal.library.user..")
.applicationServices("io.wkrzywiec.hexagonal.library.user.application..")
.adapter("infrastructure", "io.wkrzywiec.hexagonal.library.user.infrastructure..");
@ArchTest
public static final ArchRule noSpringDependenciesInUserFacade =
noClass(UserFacade.class)
.should()
.dependOnClassesThat()
.resideInAPackage("org.springframework..");
}

View File

@@ -1,6 +1,7 @@
package io.wkrzywiec.hexagonal.library.borrowing.infrastructure;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.BookTestData;
import io.wkrzywiec.hexagonal.library.UserTestData;
import io.wkrzywiec.hexagonal.library.borrowing.model.ActiveUser;
import io.wkrzywiec.hexagonal.library.borrowing.model.AvailableBook;
import io.wkrzywiec.hexagonal.library.borrowing.model.ReservationDetails;
@@ -41,7 +42,7 @@ public class BorrowingDatabaseAdapterITCase {
Long bookId = jdbcTemplate.queryForObject(
"SELECT id FROM book WHERE title = ?",
Long.class,
TestData.homoDeusBookTitle());
BookTestData.homoDeusBookTitle());
//when
database.setBookAvailable(bookId);
@@ -63,7 +64,7 @@ public class BorrowingDatabaseAdapterITCase {
Long bookId = jdbcTemplate.queryForObject(
"SELECT id FROM book WHERE title = ?",
Long.class,
TestData.homoDeusBookTitle());
BookTestData.homoDeusBookTitle());
//when
Optional<AvailableBook> availableBookOptional = database.getAvailableBook(bookId);
@@ -82,7 +83,7 @@ public class BorrowingDatabaseAdapterITCase {
Long activeUserId = jdbcTemplate.queryForObject(
"SELECT id FROM user WHERE email = ?",
Long.class,
"john.doe@test.com");
UserTestData.johnDoeEmail());
//when
Optional<ActiveUser> activeUserOptional = database.getActiveUser(activeUserId);
@@ -101,12 +102,12 @@ public class BorrowingDatabaseAdapterITCase {
Long bookId = jdbcTemplate.queryForObject(
"SELECT id FROM book WHERE title = ?",
Long.class,
TestData.homoDeusBookTitle());
BookTestData.homoDeusBookTitle());
Long activeUserId = jdbcTemplate.queryForObject(
"SELECT id FROM user WHERE email = ?",
Long.class,
"john.doe@test.com");
UserTestData.johnDoeEmail());
ReservedBook reservedBook = new ReservedBook(bookId, activeUserId);

View File

@@ -1,6 +1,7 @@
package io.wkrzywiec.hexagonal.library.email;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.BookTestData;
import io.wkrzywiec.hexagonal.library.UserTestData;
import io.wkrzywiec.hexagonal.library.email.model.SendReservationConfirmationCommand;
import io.wkrzywiec.hexagonal.library.email.ports.outgoing.EmailSender;
import org.junit.jupiter.api.BeforeEach;
@@ -22,8 +23,8 @@ public class EmailFacadeTest {
emailSender = new EmailSenderFake();
facade = new EmailFacade(emailSender, database);
database.bookTitles.put(1L, TestData.homoDeusBookTitle());
database.emailAddresses.put(1L, "john.doe@test.com");
database.bookTitles.put(1L, BookTestData.homoDeusBookTitle());
database.emailAddresses.put(1L, UserTestData.johnDoeEmail());
}
@Test

View File

@@ -1,6 +1,7 @@
package io.wkrzywiec.hexagonal.library.email.infrastructure;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.BookTestData;
import io.wkrzywiec.hexagonal.library.UserTestData;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -36,13 +37,13 @@ public class EmailDatabaseAdapterITCase {
Long bookId = jdbcTemplate.queryForObject(
"SELECT id FROM book WHERE title = ?",
Long.class,
TestData.homoDeusBookTitle());
BookTestData.homoDeusBookTitle());
//when
Optional<String> bookTitle = emailDatabase.getTitleByBookId(bookId);
//then
assertEquals(Optional.of(TestData.homoDeusBookTitle()), bookTitle);
assertEquals(Optional.of(BookTestData.homoDeusBookTitle()), bookTitle);
}
@Test
@@ -54,7 +55,7 @@ public class EmailDatabaseAdapterITCase {
Long bookId = jdbcTemplate.queryForObject(
"SELECT id FROM book WHERE title = ?",
Long.class,
TestData.homoDeusBookTitle());
BookTestData.homoDeusBookTitle());
//when
Optional<String> bookTitle = emailDatabase.getTitleByBookId(bookId + 1124);
@@ -72,13 +73,13 @@ public class EmailDatabaseAdapterITCase {
Long userId = jdbcTemplate.queryForObject(
"SELECT id FROM user WHERE email = ?",
Long.class,
"john.doe@test.com");
UserTestData.johnDoeEmail());
//when
Optional<String> emailAddress = emailDatabase.getUserEmailAddress(userId);
//then
assertEquals(Optional.of("john.doe@test.com"), emailAddress);
assertEquals(Optional.of(UserTestData.johnDoeEmail()), emailAddress);
}
@Test
@@ -90,7 +91,7 @@ public class EmailDatabaseAdapterITCase {
Long userId = jdbcTemplate.queryForObject(
"SELECT id FROM user WHERE email = ?",
Long.class,
"john.doe@test.com");
UserTestData.johnDoeEmail());
//when
Optional<String> emailAddress = emailDatabase.getUserEmailAddress(userId + 1124);

View File

@@ -1,6 +1,6 @@
package io.wkrzywiec.hexagonal.library.inventory;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.BookTestData;
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
import io.wkrzywiec.hexagonal.library.inventory.ports.outgoing.GetBookDetails;
@@ -14,8 +14,8 @@ public class GetBookDetailsFake implements GetBookDetails {
public GetBookDetailsFake() {
books = new HashMap<String, Book>();
books.put(
TestData.homoDeusBookGoogleId(),
TestData.homoDeusBook());
BookTestData.homoDeusBookGoogleId(),
BookTestData.homoDeusBook());
}
@Override

View File

@@ -1,6 +1,6 @@
package io.wkrzywiec.hexagonal.library.inventory;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.BookTestData;
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;
@@ -33,7 +33,7 @@ public class InventoryFacadeTest {
//given
AddNewBookCommand externalBookId = AddNewBookCommand
.builder()
.googleBookId(TestData.homoDeusBookGoogleId())
.googleBookId(BookTestData.homoDeusBookGoogleId())
.build();
//when

View File

@@ -1,6 +1,6 @@
package io.wkrzywiec.hexagonal.library.inventory.infrastructure;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.BookTestData;
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
@@ -31,14 +31,14 @@ public class GoogleBooksAdapterITCase {
@DisplayName("Get book details from Google Books")
public void givenCorrectBookId_whenGetBookDetails_thenReturnBookDetailsDTO(){
//given
String homoDeusResponse = TestData.homoDeusGooleBooksResponse();
Book homoDeusBook = TestData.homoDeusBook();
String homoDeusResponse = BookTestData.homoDeusGooleBooksResponse();
Book homoDeusBook = BookTestData.homoDeusBook();
server.expect(requestTo(
"https://www.googleapis.com/books/v1/volumes/" + TestData.homoDeusBookGoogleId()))
"https://www.googleapis.com/books/v1/volumes/" + BookTestData.homoDeusBookGoogleId()))
.andRespond(withSuccess(homoDeusResponse, MediaType.APPLICATION_JSON));
//when
Book actualBook= googleBooks.handle(TestData.homoDeusBookGoogleId());
Book actualBook= googleBooks.handle(BookTestData.homoDeusBookGoogleId());
//then
assertEquals(homoDeusBook, actualBook);

View File

@@ -1,6 +1,6 @@
package io.wkrzywiec.hexagonal.library.inventory.infrastructure;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.BookTestData;
import io.wkrzywiec.hexagonal.library.inventory.model.Book;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
@@ -34,7 +34,7 @@ public class InventoryDatabaseAdapterITCase {
@Sql(scripts = "/clean-database.sql", executionPhase = AFTER_TEST_METHOD)
public void givenBook_whenSaveIt_thenBookIsSaved() {
//given
Book homoDeusBook = TestData.homoDeusBook();
Book homoDeusBook = BookTestData.homoDeusBook();
//when
Book savedBook = database.save(homoDeusBook);

View File

@@ -2,7 +2,7 @@ package io.wkrzywiec.hexagonal.library.query;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.wkrzywiec.hexagonal.library.TestData;
import io.wkrzywiec.hexagonal.library.BookTestData;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@@ -32,7 +32,7 @@ public class GoogleBookSearchClientITCase {
@DisplayName("Search for a book")
public void whenSearchForBooks_thenGetListOfBooks(){
//given
String harryPotterSearchResponse = TestData.harryPotterSearchResponse();
String harryPotterSearchResponse = BookTestData.harryPotterSearchResponse();
server.expect(requestTo(
"https://www.googleapis.com/books/v1/volumes?langRestrict=en&maxResults=40&printType=books&q=" + "harry%20potter"))
.andRespond(withSuccess(harryPotterSearchResponse, MediaType.APPLICATION_JSON));
@@ -46,7 +46,7 @@ public class GoogleBookSearchClientITCase {
@DisplayName("Search for a book and get empty result")
public void whenSearchForBooks_thenGetEmptyResult(){
//given
String noBooksResponse = TestData.noBooksSearchResponse();
String noBooksResponse = BookTestData.noBooksSearchResponse();
server.expect(requestTo(
"https://www.googleapis.com/books/v1/volumes?langRestrict=en&maxResults=40&printType=books&q=" + "djfjbasdknl"))
.andRespond(withSuccess(noBooksResponse, MediaType.APPLICATION_JSON));

View File

@@ -0,0 +1,26 @@
package io.wkrzywiec.hexagonal.library.user;
import io.wkrzywiec.hexagonal.library.user.model.User;
import io.wkrzywiec.hexagonal.library.user.model.UserIdentifier;
import io.wkrzywiec.hexagonal.library.user.ports.outgoing.UserDatabase;
import org.apache.commons.lang3.reflect.FieldUtils;
import java.util.concurrent.ConcurrentHashMap;
public class InMemoryUserDatabase implements UserDatabase {
ConcurrentHashMap<Long, User> users = new ConcurrentHashMap<>();
@Override
public UserIdentifier save(User user) {
Long id = users.size() + 1L;
try {
FieldUtils.writeField(user, "id", id, true);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
users.put(id, user);
return new UserIdentifier(id);
}
}

View File

@@ -0,0 +1,49 @@
package io.wkrzywiec.hexagonal.library.user;
import io.wkrzywiec.hexagonal.library.UserTestData;
import io.wkrzywiec.hexagonal.library.user.model.AddUserCommand;
import io.wkrzywiec.hexagonal.library.user.model.EmailAddress;
import io.wkrzywiec.hexagonal.library.user.model.User;
import io.wkrzywiec.hexagonal.library.user.model.UserIdentifier;
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.assertTrue;
public class UserFacadeTest {
private InMemoryUserDatabase database;
private UserFacade facade;
@BeforeEach
public void init(){
database = new InMemoryUserDatabase();
facade = new UserFacade(database);
}
@Test
@DisplayName("Add new user")
public void shouldAddNewUser(){
//given
User expectedUser = new User(
new EmailAddress(UserTestData.johnDoeEmail()),
"John",
"Doe"
);
AddUserCommand addUserCommand = AddUserCommand.builder()
.email(UserTestData.johnDoeEmail())
.firstName("John")
.lastName("Doe")
.build();
//when
UserIdentifier userIdentifier = facade.handle(addUserCommand);
//then
assertTrue(userIdentifier.getAsLong() > 0);
assertEquals(expectedUser, database.users.get(userIdentifier.getAsLong()));
}
}

View File

@@ -0,0 +1,56 @@
package io.wkrzywiec.hexagonal.library.user.infrastructure;
import io.wkrzywiec.hexagonal.library.UserTestData;
import io.wkrzywiec.hexagonal.library.user.model.EmailAddress;
import io.wkrzywiec.hexagonal.library.user.model.User;
import io.wkrzywiec.hexagonal.library.user.model.UserIdentifier;
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.jdbc.core.JdbcTemplate;
import org.springframework.test.context.jdbc.Sql;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD;
@SpringBootTest
public class UserDatabaseAdapterITCase {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private UserRepository userRepository;
private UserDatabaseAdapter userDatabase;
@BeforeEach
public void init(){
userDatabase = new UserDatabaseAdapter(userRepository);
}
@Test
@DisplayName("Save new user in database")
@Sql(scripts = "/clean-database.sql", executionPhase = AFTER_TEST_METHOD)
public void shouldSaveDatabase(){
//given
User user = new User(
new EmailAddress(UserTestData.johnDoeEmail()),
"John",
"Doe"
);
//when
UserIdentifier userIdentifier = userDatabase.save(user);
//then
Long savedUserId = jdbcTemplate.queryForObject(
"SELECT id FROM user WHERE email = ?",
Long.class,
UserTestData.johnDoeEmail());
assertEquals(userIdentifier.getAsLong(), savedUserId);
}
}