Add tests

This commit is contained in:
Kenny Bastani
2016-12-09 18:28:12 -08:00
parent 38109cf433
commit 49564bfaca
14 changed files with 464 additions and 226 deletions

View File

@@ -2,10 +2,8 @@ package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@SpringBootApplication
@EnableJpaAuditing
public class AccountServiceApplication {
public static void main(String[] args) {

View File

@@ -36,6 +36,13 @@ public class Account extends BaseEntity {
status = AccountStatus.ACCOUNT_CREATED;
}
public Account(Long userId, String accountNumber, Boolean defaultAccount) {
this();
this.accountNumber = accountNumber;
this.defaultAccount = defaultAccount;
this.userId = userId;
}
public Account(String accountNumber, Boolean defaultAccount, AccountStatus status) {
this.accountNumber = accountNumber;
this.defaultAccount = defaultAccount;

View File

@@ -1,89 +1,266 @@
package demo.account;
import demo.event.AccountEvent;
import demo.event.AccountEvents;
import demo.event.EventController;
import demo.event.EventService;
import org.springframework.hateoas.LinkBuilder;
import org.springframework.hateoas.Resource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import java.util.Optional;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
@RestController
@RequestMapping("/v1")
public class AccountController {
private final AccountService accountService;
private final EventService eventService;
public AccountController(AccountService accountService) {
public AccountController(AccountService accountService, EventService eventService) {
this.accountService = accountService;
this.eventService = eventService;
}
@PostMapping(path = "/accounts")
public ResponseEntity createAccount(@RequestBody Account account) {
return Optional.ofNullable(accountService.createAccountResource(account))
return Optional.ofNullable(createAccountResource(account))
.map(e -> new ResponseEntity<>(e, HttpStatus.CREATED))
.orElseThrow(() -> new IllegalArgumentException("Account creation failed"));
}
@PutMapping(path = "/accounts/{id}")
public ResponseEntity updateAccount(@RequestBody Account account, @PathVariable Long id) {
return Optional.ofNullable(accountService.updateAccountResource(id, account))
return Optional.ofNullable(updateAccountResource(id, account))
.map(e -> new ResponseEntity<>(e, HttpStatus.OK))
.orElseThrow(() -> new IllegalArgumentException("Account update failed"));
}
@GetMapping(path = "/accounts/{id}")
public ResponseEntity getAccount(@PathVariable Long id) {
return Optional.ofNullable(accountService.getAccountResource(id))
return Optional.ofNullable(getAccountResource(id))
.map(e -> new ResponseEntity<>(e, HttpStatus.OK))
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
}
@GetMapping(path = "/accounts/{id}/events")
public ResponseEntity getAccountEvents(@PathVariable Long id) {
return Optional.ofNullable(accountService.getAccountEventResources(id))
return Optional.ofNullable(getAccountEventResources(id))
.map(e -> new ResponseEntity<>(e, HttpStatus.OK))
.orElseThrow(() -> new IllegalArgumentException("Could not get account events"));
}
@PostMapping(path = "/accounts/{id}/events")
public ResponseEntity createAccount(@PathVariable Long id, @RequestBody AccountEvent event) {
return Optional.ofNullable(accountService.appendEventResource(id, event))
return Optional.ofNullable(appendEventResource(id, event))
.map(e -> new ResponseEntity<>(e, HttpStatus.CREATED))
.orElseThrow(() -> new IllegalArgumentException("Append account event failed"));
}
@GetMapping(path = "/accounts/{id}/commands")
public ResponseEntity getAccountCommands(@PathVariable Long id) {
return Optional.ofNullable(accountService.getCommandsResource(id))
return Optional.ofNullable(getCommandsResource(id))
.map(e -> new ResponseEntity<>(e, HttpStatus.OK))
.orElseThrow(() -> new IllegalArgumentException("The account could not be found"));
}
@GetMapping(path = "/accounts/{id}/commands/confirm")
public ResponseEntity confirmAccount(@PathVariable Long id) {
return Optional.ofNullable(accountService.applyCommand(id, AccountCommand.CONFIRM_ACCOUNT))
return Optional.ofNullable(getAccountResource(
accountService.applyCommand(id, AccountCommand.CONFIRM_ACCOUNT)))
.map(e -> new ResponseEntity<>(e, HttpStatus.OK))
.orElseThrow(() -> new IllegalArgumentException("The command could not be applied"));
}
@GetMapping(path = "/accounts/{id}/commands/activate")
public ResponseEntity activateAccount(@PathVariable Long id) {
return Optional.ofNullable(accountService.applyCommand(id, AccountCommand.ACTIVATE_ACCOUNT))
return Optional.ofNullable(getAccountResource(
accountService.applyCommand(id, AccountCommand.ACTIVATE_ACCOUNT)))
.map(e -> new ResponseEntity<>(e, HttpStatus.OK))
.orElseThrow(() -> new IllegalArgumentException("The command could not be applied"));
}
@GetMapping(path = "/accounts/{id}/commands/suspend")
public ResponseEntity suspendAccount(@PathVariable Long id) {
return Optional.ofNullable(accountService.applyCommand(id, AccountCommand.SUSPEND_ACCOUNT))
return Optional.ofNullable(getAccountResource(
accountService.applyCommand(id, AccountCommand.SUSPEND_ACCOUNT)))
.map(e -> new ResponseEntity<>(e, HttpStatus.OK))
.orElseThrow(() -> new IllegalArgumentException("The command could not be applied"));
}
@GetMapping(path = "/accounts/{id}/commands/archive")
public ResponseEntity archiveAccount(@PathVariable Long id) {
return Optional.ofNullable(accountService.applyCommand(id, AccountCommand.ARCHIVE_ACCOUNT))
return Optional.ofNullable(getAccountResource(
accountService.applyCommand(id, AccountCommand.ARCHIVE_ACCOUNT)))
.map(e -> new ResponseEntity<>(e, HttpStatus.OK))
.orElseThrow(() -> new IllegalArgumentException("The command could not be applied"));
}
/**
* Retrieves a hypermedia resource for {@link Account} with the specified identifier.
*
* @param id is the unique identifier for looking up the {@link Account} entity
* @return a hypermedia resource for the fetched {@link Account}
*/
private Resource<Account> getAccountResource(Long id) {
Resource<Account> accountResource = null;
// Get the account for the provided id
Account account = accountService.getAccount(id);
// If the account exists, wrap the hypermedia response
if (account != null)
accountResource = getAccountResource(account);
return accountResource;
}
/**
* Creates a new {@link Account} entity and persists the result to the repository.
*
* @param account is the {@link Account} model used to create a new account
* @return a hypermedia resource for the newly created {@link Account}
*/
private Resource<Account> createAccountResource(Account account) {
Assert.notNull(account, "Account body must not be null");
Assert.notNull(account.getUserId(), "UserId is required");
Assert.notNull(account.getAccountNumber(), "AccountNumber is required");
Assert.notNull(account.getDefaultAccount(), "DefaultAccount is required");
// Create the new account
account = accountService.createAccount(account);
return getAccountResource(account);
}
/**
* Update a {@link Account} entity for the provided identifier.
*
* @param id is the unique identifier for the {@link Account} update
* @param account is the entity representation containing any updated {@link Account} fields
* @return a hypermedia resource for the updated {@link Account}
*/
private Resource<Account> updateAccountResource(Long id, Account account) {
return getAccountResource(accountService.updateAccount(id, account));
}
/**
* Appends an {@link AccountEvent} domain event to the event log of the {@link Account}
* aggregate with the specified accountId.
*
* @param accountId is the unique identifier for the {@link Account}
* @param event is the {@link AccountEvent} that attempts to alter the state of the {@link Account}
* @return a hypermedia resource for the newly appended {@link AccountEvent}
*/
private Resource<AccountEvent> appendEventResource(Long accountId, AccountEvent event) {
Resource<AccountEvent> eventResource = null;
event = accountService.appendEvent(accountId, event);
if (event != null) {
eventResource = new Resource<>(event,
linkTo(EventController.class)
.slash("events")
.slash(event.getEventId())
.withSelfRel(),
linkTo(AccountController.class)
.slash("accounts")
.slash(accountId)
.withRel("account")
);
}
return eventResource;
}
/**
* Get the {@link AccountCommand} hypermedia resource that lists the available commands that can be applied
* to an {@link Account} entity.
*
* @param id is the {@link Account} identifier to provide command links for
* @return an {@link AccountCommandsResource} with a collection of embedded command links
*/
private AccountCommandsResource getCommandsResource(Long id) {
// Get the account resource for the identifier
Resource<Account> accountResource = getAccountResource(id);
// Create a new account commands hypermedia resource
AccountCommandsResource commandResource = new AccountCommandsResource();
// Add account command hypermedia links
if (accountResource != null) {
commandResource.add(
getCommandLinkBuilder(id)
.slash("confirm")
.withRel("confirm"),
getCommandLinkBuilder(id)
.slash("activate")
.withRel("activate"),
getCommandLinkBuilder(id)
.slash("suspend")
.withRel("suspend"),
getCommandLinkBuilder(id)
.slash("archive")
.withRel("archive")
);
}
return commandResource;
}
/**
* Get {@link AccountEvents} for the supplied {@link Account} identifier.
*
* @param id is the unique identifier of the {@link Account}
* @return a list of {@link AccountEvent} wrapped in a hypermedia {@link AccountEvents} resource
*/
private AccountEvents getAccountEventResources(Long id) {
return eventService.getEvents(id);
}
/**
* Generate a {@link LinkBuilder} for generating the {@link AccountCommandsResource}.
*
* @param id is the unique identifier for a {@link Account}
* @return a {@link LinkBuilder} for the {@link AccountCommandsResource}
*/
private LinkBuilder getCommandLinkBuilder(Long id) {
return linkTo(AccountController.class)
.slash("accounts")
.slash(id)
.slash("commands");
}
/**
* Get a hypermedia enriched {@link Account} entity.
*
* @param account is the {@link Account} to enrich with hypermedia links
* @return is a hypermedia enriched resource for the supplied {@link Account} entity
*/
private Resource<Account> getAccountResource(Account account) {
Resource<Account> accountResource;
// Prepare hypermedia response
accountResource = new Resource<>(account,
linkTo(AccountController.class)
.slash("accounts")
.slash(account.getAccountId())
.withSelfRel(),
linkTo(AccountController.class)
.slash("accounts")
.slash(account.getAccountId())
.slash("events")
.withRel("events"),
getCommandLinkBuilder(account.getAccountId())
.withRel("commands")
);
return accountResource;
}
}

View File

@@ -1,8 +1,8 @@
package demo.account;
import demo.event.*;
import org.springframework.hateoas.LinkBuilder;
import org.springframework.hateoas.Resource;
import demo.event.AccountEvent;
import demo.event.AccountEventType;
import demo.event.EventService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
@@ -11,7 +11,6 @@ import java.util.Arrays;
import java.util.Objects;
import static demo.account.AccountStatus.*;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
/**
* The {@link AccountService} provides transactional support for managing {@link Account}
@@ -34,84 +33,6 @@ public class AccountService {
this.eventService = eventService;
}
/**
* Retrieves a hypermedia resource for {@link Account} with the specified identifier.
*
* @param id is the unique identifier for looking up the {@link Account} entity
* @return a hypermedia resource for the fetched {@link Account}
*/
public Resource<Account> getAccountResource(Long id) {
Resource<Account> accountResource = null;
// Get the account for the provided id
Account account = getAccount(id);
// If the account exists, wrap the hypermedia response
if (account != null)
accountResource = getAccountResource(account);
return accountResource;
}
/**
* Creates a new {@link Account} entity and persists the result to the repository.
*
* @param account is the {@link Account} model used to create a new account
* @return a hypermedia resource for the newly created {@link Account}
*/
public Resource<Account> createAccountResource(Account account) {
Assert.notNull(account, "Account body must not be null");
Assert.notNull(account.getUserId(), "UserId is required");
Assert.notNull(account.getAccountNumber(), "AccountNumber is required");
Assert.notNull(account.getDefaultAccount(), "DefaultAccount is required");
// Create the new account
account = createAccount(account);
return getAccountResource(account);
}
/**
* Update a {@link Account} entity for the provided identifier.
*
* @param id is the unique identifier for the {@link Account} update
* @param account is the entity representation containing any updated {@link Account} fields
* @return a hypermedia resource for the updated {@link Account}
*/
public Resource<Account> updateAccountResource(Long id, Account account) {
return getAccountResource(updateAccount(id, account));
}
/**
* Appends an {@link AccountEvent} domain event to the event log of the {@link Account}
* aggregate with the specified accountId.
*
* @param accountId is the unique identifier for the {@link Account}
* @param event is the {@link AccountEvent} that attempts to alter the state of the {@link Account}
* @return a hypermedia resource for the newly appended {@link AccountEvent}
*/
public Resource<AccountEvent> appendEventResource(Long accountId, AccountEvent event) {
Resource<AccountEvent> eventResource = null;
event = appendEvent(accountId, event);
if (event != null) {
eventResource = new Resource<>(event,
linkTo(EventController.class)
.slash("events")
.slash(event.getEventId())
.withSelfRel(),
linkTo(AccountController.class)
.slash("accounts")
.slash(accountId)
.withRel("account")
);
}
return eventResource;
}
/**
* Apply an {@link AccountCommand} to the {@link Account} with a specified identifier.
*
@@ -119,21 +40,21 @@ public class AccountService {
* @param accountCommand is the command to apply to the {@link Account}
* @return a hypermedia resource containing the updated {@link Account}
*/
public Resource<Account> applyCommand(Long id, AccountCommand accountCommand) {
Resource<Account> account = getAccountResource(id);
public Account applyCommand(Long id, AccountCommand accountCommand) {
Account account = getAccount(id);
Assert.notNull(account, "The account for the supplied id could not be found");
AccountStatus status = account.getContent().getStatus();
AccountStatus status = account.getStatus();
switch (accountCommand) {
case CONFIRM_ACCOUNT:
Assert.isTrue(status == ACCOUNT_PENDING, "The account has already been confirmed");
// Confirm the account
Account updateAccount = account.getContent();
Account updateAccount = account;
updateAccount.setStatus(ACCOUNT_CONFIRMED);
account = updateAccountResource(id, updateAccount);
account = updateAccount(id, updateAccount);
appendEvent(id, new AccountEvent(AccountEventType.ACCOUNT_CONFIRMED));
break;
case ACTIVATE_ACCOUNT:
@@ -142,24 +63,24 @@ public class AccountService {
.contains(status), "The account cannot be activated");
// Activate the account
account.getContent().setStatus(ACCOUNT_ACTIVE);
account = updateAccountResource(id, account.getContent());
account.setStatus(ACCOUNT_ACTIVE);
account = updateAccount(id, account);
appendEvent(id, new AccountEvent(AccountEventType.ACCOUNT_ACTIVATED));
break;
case SUSPEND_ACCOUNT:
Assert.isTrue(status == ACCOUNT_ACTIVE, "An inactive account cannot be suspended");
// Suspend the account
account.getContent().setStatus(ACCOUNT_SUSPENDED);
account = updateAccountResource(id, account.getContent());
account.setStatus(ACCOUNT_SUSPENDED);
account = updateAccount(id, account);
appendEvent(id, new AccountEvent(AccountEventType.ACCOUNT_SUSPENDED));
break;
case ARCHIVE_ACCOUNT:
Assert.isTrue(status == ACCOUNT_ACTIVE, "An inactive account cannot be archived");
// Archive the account
account.getContent().setStatus(ACCOUNT_ARCHIVED);
account = updateAccountResource(id, account.getContent());
account.setStatus(ACCOUNT_ARCHIVED);
account = updateAccount(id, account);
appendEvent(id, new AccountEvent(AccountEventType.ACCOUNT_ARCHIVED));
break;
default:
@@ -170,90 +91,6 @@ public class AccountService {
return account;
}
/**
* Get the {@link AccountCommand} hypermedia resource that lists the available commands that can be applied
* to an {@link Account} entity.
*
* @param id is the {@link Account} identifier to provide command links for
* @return an {@link AccountCommandsResource} with a collection of embedded command links
*/
public AccountCommandsResource getCommandsResource(Long id) {
// Get the account resource for the identifier
Resource<Account> accountResource = getAccountResource(id);
// Create a new account commands hypermedia resource
AccountCommandsResource commandResource = new AccountCommandsResource();
// Add account command hypermedia links
if (accountResource != null) {
commandResource.add(
getCommandLinkBuilder(id)
.slash("confirm")
.withRel("confirm"),
getCommandLinkBuilder(id)
.slash("activate")
.withRel("activate"),
getCommandLinkBuilder(id)
.slash("suspend")
.withRel("suspend"),
getCommandLinkBuilder(id)
.slash("archive")
.withRel("archive")
);
}
return commandResource;
}
/**
* Get {@link AccountEvents} for the supplied {@link Account} identifier.
*
* @param id is the unique identifier of the {@link Account}
* @return a list of {@link AccountEvent} wrapped in a hypermedia {@link AccountEvents} resource
*/
public AccountEvents getAccountEventResources(Long id) {
return eventService.getEvents(id);
}
/**
* Generate a {@link LinkBuilder} for generating the {@link AccountCommandsResource}.
*
* @param id is the unique identifier for a {@link Account}
* @return a {@link LinkBuilder} for the {@link AccountCommandsResource}
*/
private LinkBuilder getCommandLinkBuilder(Long id) {
return linkTo(AccountController.class)
.slash("accounts")
.slash(id)
.slash("commands");
}
/**
* Get a hypermedia enriched {@link Account} entity.
*
* @param account is the {@link Account} to enrich with hypermedia links
* @return is a hypermedia enriched resource for the supplied {@link Account} entity
*/
private Resource<Account> getAccountResource(Account account) {
Resource<Account> accountResource;
// Prepare hypermedia response
accountResource = new Resource<>(account,
linkTo(AccountController.class)
.slash("accounts")
.slash(account.getAccountId())
.withSelfRel(),
linkTo(AccountController.class)
.slash("accounts")
.slash(account.getAccountId())
.slash("events")
.withRel("events"),
getCommandLinkBuilder(account.getAccountId())
.withRel("commands")
);
return accountResource;
}
/**
* Get an {@link Account} entity for the supplied identifier.
@@ -261,7 +98,7 @@ public class AccountService {
* @param id is the unique identifier of a {@link Account} entity
* @return an {@link Account} entity
*/
private Account getAccount(Long id) {
public Account getAccount(Long id) {
return accountRepository.findOne(id);
}
@@ -271,7 +108,7 @@ public class AccountService {
* @param account is the {@link Account} to create
* @return the newly created {@link Account}
*/
private Account createAccount(Account account) {
public Account createAccount(Account account) {
// Assert for uniqueness constraint
Assert.isNull(accountRepository.findAccountByUserId(account.getUserId()),
"An account with the supplied userId already exists");
@@ -282,7 +119,7 @@ public class AccountService {
account = accountRepository.save(account);
// Trigger the account creation event
appendEventResource(account.getAccountId(),
appendEvent(account.getAccountId(),
new AccountEvent(AccountEventType.ACCOUNT_CREATED));
return account;
@@ -295,11 +132,11 @@ public class AccountService {
* @param account is the {@link Account} containing updated fields
* @return the updated {@link Account} entity
*/
private Account updateAccount(Long id, Account account) {
public Account updateAccount(Long id, Account account) {
Assert.notNull(id, "Account id must be present in the resource URL");
Assert.notNull(account, "Account request body cannot be null");
if(account.getAccountId() != null) {
if (account.getAccountId() != null) {
Assert.isTrue(Objects.equals(id, account.getAccountId()),
"The account id in the request body must match the resource URL");
} else {
@@ -322,11 +159,11 @@ public class AccountService {
* @param event is the {@link AccountEvent} to append to the {@link Account} entity
* @return the newly appended {@link AccountEvent}
*/
private AccountEvent appendEvent(Long accountId, AccountEvent event) {
public AccountEvent appendEvent(Long accountId, AccountEvent event) {
Account account = getAccount(accountId);
Assert.notNull(account, "The account with the supplied id does not exist");
event.setAccount(account);
event = eventService.createEvent(event).getContent();
event = eventService.createEvent(event);
account.getEvents().add(event);
accountRepository.save(account);
return event;

View File

@@ -1,4 +1,4 @@
package demo;
package demo.config;
import demo.account.Account;
import demo.account.AccountController;

View File

@@ -1,4 +1,4 @@
package demo;
package demo.config;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;

View File

@@ -0,0 +1,13 @@
package demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
/**
* Enable JPA auditing on an empty configuration class to disable auditing on
*
*/
@Configuration
@EnableJpaAuditing
public class JpaConfig {
}

View File

@@ -50,23 +50,18 @@ public class EventService {
* @param event is the {@link AccountEvent} to publish to the account stream
* @return a hypermedia {@link AccountEvent} resource
*/
public Resource<AccountEvent> createEvent(AccountEvent event) {
Resource<AccountEvent> eventResource = null;
public AccountEvent createEvent(AccountEvent event) {
// Save new event
event = addEvent(event);
Assert.notNull(event, "The event could not be appended to the account");
// Create account event resource
eventResource = getAccountEventResource(event);
// Append the account event to the stream
accountStreamSource.output()
.send(MessageBuilder
.withPayload(eventResource)
.withPayload(getAccountEventResource(event))
.build());
return eventResource;
return event;
}
/**

View File

@@ -9,4 +9,6 @@ spring:
bindings:
output:
destination: account
contentType: 'application/json'
contentType: 'application/json'
server:
port: 0

View File

@@ -1,5 +1,4 @@
spring:
application:
name: account-web
server:
port: 0
---

View File

@@ -1,16 +0,0 @@
package demo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class AccountServiceApplicationTests {
@Test
public void contextLoads() {
}
}

View File

@@ -0,0 +1,43 @@
package demo.account;
import demo.event.EventService;
import org.junit.Test;
import org.junit.runner.RunWith;
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.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@WebMvcTest(AccountController.class)
public class AccountControllerTest {
@Autowired
private MockMvc mvc;
@MockBean
private AccountService accountService;
@MockBean
private EventService eventService;
@Test
public void getUserAccountResourceShouldReturnAccount() throws Exception {
String content = "{\"userId\": 1, \"accountNumber\": \"123456789\", \"defaultAccount\": true}";
Account account = new Account(1L, "123456789", true);
given(this.accountService.getAccount(1L))
.willReturn(account);
this.mvc.perform(get("/v1/accounts/1").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andExpect(content().json(content));
}
}

View File

@@ -0,0 +1,182 @@
package demo.account;
import demo.event.AccountEvent;
import demo.event.AccountEventType;
import demo.event.EventService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
@RunWith(SpringRunner.class)
public class AccountServiceTests {
@MockBean
private EventService eventService;
@MockBean
private AccountRepository accountRepository;
private AccountService accountService;
@Before
public void before() {
accountService = new AccountService(accountRepository, eventService);
}
@Test
public void getAccountReturnsAccount() throws Exception {
Account expected = new Account(1L, "123456789", true);
expected.setUserId(1L);
given(this.accountRepository.findOne(1L)).willReturn(expected);
Account actual = accountService.getAccount(1L);
assertThat(actual).isNotNull();
assertThat(actual.getUserId()).isEqualTo(1L);
assertThat(actual.getAccountNumber()).isEqualTo("123456789");
}
@Test
public void createAccountReturnsAccount() throws Exception {
Account expected = new Account(1L, "123456789", true);
expected.setUserId(1L);
Account actual = accountService.createAccount(expected);
assertThat(actual).isNotNull();
assertThat(actual.getStatus()).isEqualTo(AccountStatus.ACCOUNT_CREATED);
assertThat(actual.getUserId()).isEqualTo(1L);
assertThat(actual.getAccountNumber()).isEqualTo("123456789");
}
@Test
public void applyCommandSuspendsAccount() throws Exception {
Account account = new Account(1L, "123456789", true);
account.setStatus(AccountStatus.ACCOUNT_ACTIVE);
account.setUserId(1L);
AccountEvent accountEvent = new AccountEvent(AccountEventType.ACCOUNT_SUSPENDED);
accountEvent.setAccount(account);
accountEvent.setEventId(1L);
given(this.accountRepository.findOne(1L)).willReturn(account);
given(this.accountRepository.save(account)).willReturn(account);
given(this.eventService.createEvent(new AccountEvent(AccountEventType.ACCOUNT_SUSPENDED)))
.willReturn(accountEvent);
Account actual = accountService.applyCommand(1L, AccountCommand.SUSPEND_ACCOUNT);
assertThat(actual).isNotNull();
assertThat(actual.getStatus()).isEqualTo(AccountStatus.ACCOUNT_SUSPENDED);
}
@Test
public void applyCommandUnsuspendsAccount() throws Exception {
Account account = new Account(1L, "123456789", true);
account.setStatus(AccountStatus.ACCOUNT_SUSPENDED);
account.setUserId(1L);
AccountEvent accountEvent = new AccountEvent(AccountEventType.ACCOUNT_ACTIVATED);
accountEvent.setAccount(account);
accountEvent.setEventId(1L);
given(this.accountRepository.findOne(1L)).willReturn(account);
given(this.accountRepository.save(account)).willReturn(account);
given(this.eventService.createEvent(new AccountEvent(AccountEventType.ACCOUNT_ACTIVATED)))
.willReturn(accountEvent);
Account actual = accountService.applyCommand(1L, AccountCommand.ACTIVATE_ACCOUNT);
assertThat(actual).isNotNull();
assertThat(actual.getStatus()).isEqualTo(AccountStatus.ACCOUNT_ACTIVE);
}
@Test
public void applyCommandArchivesAccount() throws Exception {
Account account = new Account(1L, "123456789", true);
account.setStatus(AccountStatus.ACCOUNT_ACTIVE);
account.setUserId(1L);
AccountEvent accountEvent = new AccountEvent(AccountEventType.ACCOUNT_ARCHIVED);
accountEvent.setAccount(account);
accountEvent.setEventId(1L);
given(this.accountRepository.findOne(1L)).willReturn(account);
given(this.accountRepository.save(account)).willReturn(account);
given(this.eventService.createEvent(new AccountEvent(AccountEventType.ACCOUNT_ARCHIVED)))
.willReturn(accountEvent);
Account actual = accountService.applyCommand(1L, AccountCommand.ARCHIVE_ACCOUNT);
assertThat(actual).isNotNull();
assertThat(actual.getStatus()).isEqualTo(AccountStatus.ACCOUNT_ARCHIVED);
}
@Test
public void applyCommmandUnarchivesAccount() throws Exception {
Account account = new Account(1L, "123456789", true);
account.setStatus(AccountStatus.ACCOUNT_ARCHIVED);
account.setUserId(1L);
AccountEvent accountEvent = new AccountEvent(AccountEventType.ACCOUNT_ACTIVATED);
accountEvent.setAccount(account);
accountEvent.setEventId(1L);
given(this.accountRepository.findOne(1L)).willReturn(account);
given(this.accountRepository.save(account)).willReturn(account);
given(this.eventService.createEvent(new AccountEvent(AccountEventType.ACCOUNT_ACTIVATED)))
.willReturn(accountEvent);
Account actual = accountService.applyCommand(1L, AccountCommand.ACTIVATE_ACCOUNT);
assertThat(actual).isNotNull();
assertThat(actual.getStatus()).isEqualTo(AccountStatus.ACCOUNT_ACTIVE);
}
@Test
public void applyCommmandConfirmsAccount() throws Exception {
Account account = new Account(1L, "123456789", true);
account.setStatus(AccountStatus.ACCOUNT_PENDING);
account.setUserId(1L);
AccountEvent accountEvent = new AccountEvent(AccountEventType.ACCOUNT_CONFIRMED);
accountEvent.setAccount(account);
accountEvent.setEventId(1L);
given(this.accountRepository.findOne(1L)).willReturn(account);
given(this.accountRepository.save(account)).willReturn(account);
given(this.eventService.createEvent(new AccountEvent(AccountEventType.ACCOUNT_CONFIRMED)))
.willReturn(accountEvent);
Account actual = accountService.applyCommand(1L, AccountCommand.CONFIRM_ACCOUNT);
assertThat(actual).isNotNull();
assertThat(actual.getStatus()).isEqualTo(AccountStatus.ACCOUNT_CONFIRMED);
}
@Test
public void applyCommmandActivatesAccount() throws Exception {
Account account = new Account(1L, "123456789", true);
account.setStatus(AccountStatus.ACCOUNT_CONFIRMED);
account.setUserId(1L);
AccountEvent accountEvent = new AccountEvent(AccountEventType.ACCOUNT_ACTIVATED);
accountEvent.setAccount(account);
accountEvent.setEventId(1L);
given(this.accountRepository.findOne(1L)).willReturn(account);
given(this.accountRepository.save(account)).willReturn(account);
given(this.eventService.createEvent(new AccountEvent(AccountEventType.ACCOUNT_ACTIVATED)))
.willReturn(accountEvent);
Account actual = accountService.applyCommand(1L, AccountCommand.ACTIVATE_ACCOUNT);
assertThat(actual).isNotNull();
assertThat(actual.getStatus()).isEqualTo(AccountStatus.ACCOUNT_ACTIVE);
}
}

View File

@@ -0,0 +1 @@
INSERT INTO ACCOUNT(ID, USER_ID, ACCOUNT_NUMBER, DEFAULT_ACCOUNT) values (1, 1, '123456789', FALSE);