Skip to content

Commit

Permalink
PRMT-4850 (#262)
Browse files Browse the repository at this point in the history
* [PRMT-4850] Added `ConditionExpression` to `UpdateItemRequest`.

Signed-off-by: martin-nhs <[email protected]>

* [PRMT-4850] Started implementing unit tests.

Signed-off-by: martin-nhs <[email protected]>

* [PRMT-4850] Added additional unit test.

Signed-off-by: martin-nhs <[email protected]>

* [PRMT-4850] Enhanced unit tests.

Signed-off-by: martin-nhs <[email protected]>

* [PRMT-4850] Update methods to not use legacy code.

Signed-off-by: martin-nhs <[email protected]>

* [PRMT-4850] Updated tests to include more test cases.

Signed-off-by: martin-nhs <[email protected]>

* [PRMT-4850] Remove commented out test.

Signed-off-by: martin-nhs <[email protected]>

* [PRMT-4850] Enhance test assertions.

Signed-off-by: martin-nhs <[email protected]>

---------

Signed-off-by: martin-nhs <[email protected]>
  • Loading branch information
martin-nhs authored May 24, 2024
1 parent 6ae6954 commit 4dc6193
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import uk.nhs.prm.repo.ehrtransferservice.activemq.ForceXercesParserExtension;
import uk.nhs.prm.repo.ehrtransferservice.configuration.LocalStackAwsConfig;
import uk.nhs.prm.repo.ehrtransferservice.database.model.ConversationRecord;
import uk.nhs.prm.repo.ehrtransferservice.exceptions.base.DatabaseException;
import uk.nhs.prm.repo.ehrtransferservice.exceptions.database.ConversationNotPresentException;
import uk.nhs.prm.repo.ehrtransferservice.exceptions.database.ConversationUpdateException;
import uk.nhs.prm.repo.ehrtransferservice.exceptions.database.QueryReturnedNoItemsException;
Expand Down Expand Up @@ -124,13 +123,13 @@ void updateConversationTransferStatus_ValidInboundConversationIdAndConversationT
}

@Test
void updateConversationTransferStatus_NonExistingInboundConversationIdAndConversationTransferStatus_ShouldThrowConversationNotPresentException() {
void updateConversationTransferStatus_NonExistingInboundConversationIdAndExistingConversationTransferStatus_ShouldThrowConversationUpdateException() {
// given
final UUID inboundConversationId = UUID.randomUUID();

// when
assertThrows(ConversationNotPresentException.class, () ->
transferService.updateConversationTransferStatus(inboundConversationId, INBOUND_FAILED));
// then
assertThrows(ConversationUpdateException.class, () ->
transferService.updateConversationTransferStatus(inboundConversationId, INBOUND_FAILED));
}

@Test
Expand All @@ -154,13 +153,13 @@ void updateConversationTransferStatusWithFailure_ValidInboundConversationIdAndFa
}

@Test
void updateConversationTransferStatusWithFailure_NonExistingInboundConversationIdAndFailureCode_ShouldThrowConversationNotPresentException() {
void updateConversationTransferStatusWithFailure_NonExistingInboundConversationIdAndFailureCode_ShouldThrowConversationUpdateException() {
// given
final UUID inboundConversationId = UUID.randomUUID();
final String failureCode = "19";

// when
assertThrows(ConversationNotPresentException.class, () ->
assertThrows(ConversationUpdateException.class, () ->
transferService.updateConversationTransferStatusWithFailure(inboundConversationId, failureCode));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,7 @@ ConversationRecord findConversationByInboundConversationId(UUID inboundConversat
}

void updateConversationStatus(UUID inboundConversationId, ConversationTransferStatus conversationTransferStatus) {
if (!isInboundConversationPresent(inboundConversationId)) {
throw new ConversationNotPresentException(inboundConversationId);
}

final Map<String, AttributeValue> keyItems = new HashMap<>();
final String updateTimestamp = getIsoTimestamp();

keyItems.put(INBOUND_CONVERSATION_ID.name, AttributeValue.builder()
.s(inboundConversationId.toString().toUpperCase())
Expand All @@ -151,22 +146,23 @@ void updateConversationStatus(UUID inboundConversationId, ConversationTransferSt
.s(CONVERSATION.name())
.build());

final Map<String, AttributeValueUpdate> updateItems = new HashMap<>();

updateItems.put(TRANSFER_STATUS.name, AttributeValueUpdate.builder()
.value(AttributeValue.builder().s(conversationTransferStatus.name()).build())
.action(AttributeAction.PUT)
.build());

updateItems.put(UPDATED_AT.name, AttributeValueUpdate.builder()
.value(AttributeValue.builder().s(updateTimestamp).build())
.action(AttributeAction.PUT)
.build());

final UpdateItemRequest itemRequest = UpdateItemRequest.builder()
.tableName(config.transferTrackerDbTableName())
.key(keyItems)
.attributeUpdates(updateItems)
.updateExpression("SET #TransferStatus = :tsValue, #UpdatedAt = :uaValue")
.expressionAttributeNames(Map.of(
"#TransferStatus", TRANSFER_STATUS.name,
"#UpdatedAt", UPDATED_AT.name
))
.expressionAttributeValues(Map.of(
":tsValue", AttributeValue.builder()
.s(conversationTransferStatus.name())
.build(),
":uaValue", AttributeValue.builder()
.s(getIsoTimestamp())
.build()
))
.conditionExpression("attribute_exists(CreatedAt)")
.build();

try {
Expand All @@ -177,12 +173,7 @@ void updateConversationStatus(UUID inboundConversationId, ConversationTransferSt
}

void updateConversationStatusWithFailure(UUID inboundConversationId, String failureCode) {
if (!isInboundConversationPresent(inboundConversationId)) {
throw new ConversationNotPresentException(inboundConversationId);
}

final Map<String, AttributeValue> keyItems = new HashMap<>();
final String updateTimestamp = getIsoTimestamp();

keyItems.put(INBOUND_CONVERSATION_ID.name, AttributeValue.builder()
.s(inboundConversationId.toString().toUpperCase())
Expand All @@ -192,27 +183,27 @@ void updateConversationStatusWithFailure(UUID inboundConversationId, String fail
.s(CONVERSATION.name())
.build());

final Map<String, AttributeValueUpdate> updateItems = new HashMap<>();

updateItems.put(TRANSFER_STATUS.name, AttributeValueUpdate.builder()
.value(AttributeValue.builder().s(INBOUND_FAILED.name()).build())
.action(AttributeAction.PUT)
.build());

updateItems.put(FAILURE_CODE.name, AttributeValueUpdate.builder()
.value(AttributeValue.builder().s(failureCode).build())
.action(AttributeAction.PUT)
.build());

updateItems.put(UPDATED_AT.name, AttributeValueUpdate.builder()
.value(AttributeValue.builder().s(updateTimestamp).build())
.action(AttributeAction.PUT)
.build());

final UpdateItemRequest itemRequest = UpdateItemRequest.builder()
.tableName(config.transferTrackerDbTableName())
.key(keyItems)
.attributeUpdates(updateItems)
.updateExpression("SET #TransferStatus = :tsValue, #FailureCode = :fcValue, #UpdatedAt = :uaValue")
.expressionAttributeNames(Map.of(
"#TransferStatus", TRANSFER_STATUS.name,
"#UpdatedAt", UPDATED_AT.name,
"#FailureCode", FAILURE_CODE.name
))
.expressionAttributeValues(Map.of(
":tsValue", AttributeValue.builder()
.s(INBOUND_FAILED.name())
.build(),
":fcValue", AttributeValue.builder()
.s(failureCode)
.build(),
":uaValue", AttributeValue.builder()
.s(getIsoTimestamp())
.build()
))
.conditionExpression("attribute_exists(CreatedAt)")
.build();

try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package uk.nhs.prm.repo.ehrtransferservice.database;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import uk.nhs.prm.repo.ehrtransferservice.config.AppConfig;
import uk.nhs.prm.repo.ehrtransferservice.database.enumeration.ConversationTransferStatus;
import uk.nhs.prm.repo.ehrtransferservice.exceptions.database.ConversationUpdateException;

import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*;
import static uk.nhs.prm.repo.ehrtransferservice.database.enumeration.TransferTableAttribute.INBOUND_CONVERSATION_ID;

@ExtendWith(MockitoExtension.class)
class TransferRepositoryTest {
@Mock
private AppConfig appConfig;

@Mock
private DynamoDbClient dynamoDbClient;

@InjectMocks
private TransferRepository transferRepository;

private static final String TABLE_NAME = "ehr-transfer-tracker";
private static final String CREATED_AT_CONDITION_EXPRESSION = "attribute_exists(CreatedAt)";
private static final String UPDATE_STATUS_CODE_EXPRESSION = "SET #TransferStatus = :tsValue, #UpdatedAt = :uaValue";
private static final String UPDATE_WITH_FAILURE_CODE_EXPRESSION = "SET #TransferStatus = :tsValue, #FailureCode = :fcValue, #UpdatedAt = :uaValue";
private static final ArgumentCaptor<UpdateItemRequest> updateItemRequestCaptor = ArgumentCaptor.forClass(UpdateItemRequest.class);

@BeforeEach
void beforeEach() {
doReturn(TABLE_NAME)
.when(appConfig)
.transferTrackerDbTableName();
}

@Test
void updateConversationStatus_ValidInboundConversationIdAndStatus_ShouldCallUpdateItem() {
// given
final String inboundConversationId = "F68FE779-5A2A-490B-81FE-6976543EFC06";
final ConversationTransferStatus status = ConversationTransferStatus.INBOUND_COMPLETE;

// when
transferRepository.updateConversationStatus(UUID.fromString(inboundConversationId), status);

// then
verify(appConfig).transferTrackerDbTableName();
verify(dynamoDbClient).updateItem(updateItemRequestCaptor.capture());
assertEquals(inboundConversationId, updateItemRequestCaptor.getValue().key().get(INBOUND_CONVERSATION_ID.name).s());
assertEquals(status.name(), updateItemRequestCaptor.getValue().expressionAttributeValues().get(":tsValue").s());
assertEquals(CREATED_AT_CONDITION_EXPRESSION, updateItemRequestCaptor.getValue().conditionExpression());
assertEquals(UPDATE_STATUS_CODE_EXPRESSION, updateItemRequestCaptor.getValue().updateExpression());
}

@Test
void updateConversationStatus_ValidInboundConversationIdAndStatusWithNoCreatedAtDate_ShouldThrowConversationUpdateException() {
// given
final String inboundConversationId = "C68082F9-EFB9-4144-BAA0-3A2F2E2A88B9";
final ConversationTransferStatus status = ConversationTransferStatus.INBOUND_COMPLETE;

// when
doThrow(ConditionalCheckFailedException.class)
.when(dynamoDbClient)
.updateItem(any(UpdateItemRequest.class));

// then
assertThrows(
ConversationUpdateException.class,
() -> transferRepository.updateConversationStatus(UUID.fromString(inboundConversationId), status)
);

verify(dynamoDbClient).updateItem(updateItemRequestCaptor.capture());
assertEquals(inboundConversationId, updateItemRequestCaptor.getValue().key().get(INBOUND_CONVERSATION_ID.name).s());
}

@Test
void updateConversationStatusWithFailure_ValidInboundConversationIdAndFailureCode_ShouldCallUpdateItem() {
// given
final String inboundConversationId = "0A1B2C3D-4E5F-6789-ABCD-EF0123456789";
final String failureCode = "19";

// when
transferRepository.updateConversationStatusWithFailure(UUID.fromString(inboundConversationId), failureCode);

// then
verify(appConfig).transferTrackerDbTableName();
verify(dynamoDbClient).updateItem(updateItemRequestCaptor.capture());
assertEquals(inboundConversationId, updateItemRequestCaptor.getValue().key().get(INBOUND_CONVERSATION_ID.name).s());
assertEquals(failureCode, updateItemRequestCaptor.getValue().expressionAttributeValues().get(":fcValue").s());
assertEquals(UPDATE_WITH_FAILURE_CODE_EXPRESSION, updateItemRequestCaptor.getValue().updateExpression());
assertEquals(CREATED_AT_CONDITION_EXPRESSION, updateItemRequestCaptor.getValue().conditionExpression());
}

@Test
void updateConversationStatusWithFailure_ValidInboundConversationIdAndFailureCodeWithNoCreatedAtDate_ShouldThrowConversationUpdateException() {
// given
final String inboundConversationId = "8A9B0CAD-2E3F-4567-ABCD-EF8901234567";
final String failureCode = "19";

// when
doThrow(ConditionalCheckFailedException.class)
.when(dynamoDbClient)
.updateItem(any(UpdateItemRequest.class));

// then
assertThrows(
ConversationUpdateException.class,
() -> transferRepository.updateConversationStatusWithFailure(UUID.fromString(inboundConversationId), failureCode)
);

verify(dynamoDbClient).updateItem(updateItemRequestCaptor.capture());
assertEquals(inboundConversationId, updateItemRequestCaptor.getValue().key().get(INBOUND_CONVERSATION_ID.name).s());
}
}

0 comments on commit 4dc6193

Please sign in to comment.