Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/main/java/io/autoinvestor/domain/model/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,8 @@ private void whenHoldingUpdated(HoldingWasUpdatedEvent event) {
private void whenHoldingDeleted(HoldingWasDeletedEvent event) {
this.state = this.state.withHoldingDeleted(event);
}

public WalletState getState() {
return this.state;
}
}
4 changes: 4 additions & 0 deletions src/main/java/io/autoinvestor/domain/model/WalletState.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ public WalletState withHoldingDeleted(HoldingWasDeletedEvent event) {
holdings.remove(AssetId.of(payload.assetId()));
return new WalletState(this.walletId, this.userId, this.holdings);
}

public String getWalletIdString() {
return this.walletId.value();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import io.autoinvestor.application.HoldingsReadModel;
import io.autoinvestor.application.HoldingsReadModelDTO;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.springframework.context.annotation.Profile;
Expand All @@ -11,8 +13,17 @@
@Repository
@Profile("local")
public class InMemoryHoldingsReadModel implements HoldingsReadModel {

Collection<HoldingsReadModelDTO> holdings = new ArrayList<>();

public InMemoryHoldingsReadModel() {
holdings.add(new HoldingsReadModelDTO("user-1", "asset-1", 1, 1));
}

@Override
public void add(HoldingsReadModelDTO dto) {}
public void add(HoldingsReadModelDTO dto) {
holdings.add(dto);
}

@Override
public void update(HoldingsReadModelDTO dto) {}
Expand All @@ -24,11 +35,15 @@ public boolean delete(String userId, String assetId) {

@Override
public List<HoldingsReadModelDTO> getHoldings(String userId) {
return List.of();
return holdings.stream().filter(doc -> doc.userId().equals(userId)).toList();
}

@Override
public boolean assetAlreadyExists(String userIs, String assetId) {
return false;
}

public void clear() {
holdings.clear();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,34 @@
import io.autoinvestor.application.UsersWalletReadModel;
import io.autoinvestor.application.UsersWalletReadModelDTO;

import java.util.HashMap;
import java.util.Map;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Repository;

@Repository
@Profile("local")
public class InMemoryUsersWalletReadModel implements UsersWalletReadModel {

private final Map<String, String> readModel = new HashMap<>();

public InMemoryUsersWalletReadModel() {
readModel.put("user-1", "wallet-1");
readModel.put("user-2", "wallet-2");
}

@Override
public void add(UsersWalletReadModelDTO dto) {}
public void add(UsersWalletReadModelDTO dto) {
readModel.put(dto.userId(), dto.walletId());
}

@Override
public String getWalletId(String userId) {
return "";
return readModel.get(userId);
}

public void clear() {
readModel.clear();
}
}
91 changes: 91 additions & 0 deletions src/test/java/io/autoinvestor/PortfolioIntegrationTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package io.autoinvestor;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import io.autoinvestor.application.*;
import io.autoinvestor.application.NewHoldingUseCase.NewHoldingCommand;
import io.autoinvestor.application.NewHoldingUseCase.NewHoldingCommandHandler;
import io.autoinvestor.application.WalletCreatedUseCase.WalletCreateCommand;
import io.autoinvestor.application.WalletCreatedUseCase.WalletCreatedHandler;
import io.autoinvestor.domain.model.Wallet;
import io.autoinvestor.infrastructure.read_models.InMemoryHoldingsReadModel;
import io.autoinvestor.infrastructure.read_models.InMemoryUsersWalletReadModel;
import io.autoinvestor.infrastructure.repositories.InMemoryEventStoreRepository;

import java.util.Collection;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles("local")
class PortfolioIntegrationTest {

@Autowired private InMemoryUsersWalletReadModel readModelUserWallet;

@Autowired private WalletCreatedHandler walletCreatedCommandHandler;

@Autowired private InMemoryHoldingsReadModel holdingsReadModel;

@Autowired private NewHoldingCommandHandler newHoldingCommandHandler;

@Autowired private InMemoryEventStoreRepository eventStore;

@BeforeEach
void resetState() {
readModelUserWallet.clear();
holdingsReadModel.clear();
}

@Test
void createWalletHandler_shouldCreateWalletForUser() {
// GIVEN: a user ID that does not exist yet
String userId = "user-1";

// PRECONDITION: portfolioRepository has no wallet for "user-1"
assertThat(readModelUserWallet.getWalletId(userId)).isNull();

// WHEN: we invoke the CreateWalletCommandHandler with the id of the user
walletCreatedCommandHandler.handle(new WalletCreateCommand(userId));

// THEN: the portfolioRepository should now contain a wallet for "user-1"
assertThat(readModelUserWallet.getWalletId(userId)).isNotEmpty();
}

@Test
void createAsset_shouldCreateAssetForUser() {
String userId = "user-1";
String walletId = "wallet-1";
String assetId = "asset-id";
int amount = 1;
int boughtPrice = 1;

// Add wallet to usersWalletReadModel

// Simulate wallet creation event and save it in the event store
Wallet wallet = Wallet.create(userId);
// Wallet.create generates WalletWasCreatedEvent inside

readModelUserWallet.add(
new UsersWalletReadModelDTO(wallet.getState().getWalletIdString(), userId));
// Save the wallet creation event(s) in the event store
eventStore.save(wallet);

// Now asset should NOT exist yet
assertThat(holdingsReadModel.assetAlreadyExists(userId, assetId)).isFalse();

// Call your handler
newHoldingCommandHandler.handle(
new NewHoldingCommand(assetId, userId, amount, boughtPrice));

// Verify the holding is added
Collection<HoldingsReadModelDTO> holdingsOfUser = holdingsReadModel.getHoldings(userId);
assertThat(holdingsOfUser).extracting(HoldingsReadModelDTO::assetId).contains(assetId);
}
}
2 changes: 2 additions & 0 deletions src/test/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
spring.application.name=portfolio
spring.profiles.active=local
Loading