package com.intrasoft.ermis.transit.cargoofficeofdestination.core.service;

import com.intrasoft.ermis.common.bpmn.core.BpmnEngine;
import com.intrasoft.ermis.common.bpmn.core.CorrelateBpmnMessageCommand;
import com.intrasoft.ermis.transit.cargoofficeofdestination.domain.enums.BpmnGlobalMessageNamesEnum;
import com.intrasoft.ermis.transit.common.exceptions.BaseException;
import lombok.RequiredArgsConstructor;
import org.camunda.bpm.engine.MismatchingMessageCorrelationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class ArrivalNotificationServiceImpl implements ArrivalNotificationService {

    private static final String ERROR_MESSAGE_PREFIX = "Failed to correlate {" + BpmnGlobalMessageNamesEnum.TB007_MESSAGE_RECEIVED_MESSAGE.getValue()
            + "} BPMN message for Movement with ID: ";

    private static final String ERROR_MESSAGE_SUFFIX = ". The main process is either past the related await point, is finished or does not exist.";

    private final BpmnEngine bpmnEngine;

    @Override
    public void continueMainProcess(String movementId) throws BaseException {

        CorrelateBpmnMessageCommand command = CorrelateBpmnMessageCommand.builder()
                                                                         .messageName(BpmnGlobalMessageNamesEnum.TB007_MESSAGE_RECEIVED_MESSAGE.getValue())
                                                                         .businessKey(movementId)
                                                                         .build();

        try {
            bpmnEngine.correlateMessage(command);
        } catch (MismatchingMessageCorrelationException exception) {
            throw new BaseException(ERROR_MESSAGE_PREFIX + movementId + ERROR_MESSAGE_SUFFIX);
        }
    }
}

package com.intrasoft.ermis.transit.cargoofficeofdestination.test.service;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import com.intrasoft.ermis.common.bpmn.core.BpmnEngine;
import com.intrasoft.ermis.common.bpmn.core.CorrelateBpmnMessageCommand;
import com.intrasoft.ermis.transit.cargoofficeofdestination.core.service.ArrivalNotificationServiceImpl;
import com.intrasoft.ermis.transit.cargoofficeofdestination.domain.enums.BpmnGlobalMessageNamesEnum;
import com.intrasoft.ermis.transit.common.exceptions.BaseException;
import org.camunda.bpm.engine.MismatchingMessageCorrelationException;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
class ArrivalNotificationServiceUT {

    private static final String ERROR_MESSAGE_PREFIX = "Failed to correlate {" + BpmnGlobalMessageNamesEnum.TB007_MESSAGE_RECEIVED_MESSAGE.getValue()
            + "} BPMN message for Movement with ID: ";

    private static final String ERROR_MESSAGE_SUFFIX = ". The main process is either past the related await point, is finished or does not exist.";

    private static final String MOVEMENT_ID = "MOCK_MOVEMENT_ID";

    @Mock
    private BpmnEngine bpmnEngine;

    @InjectMocks
    private ArrivalNotificationServiceImpl arrivalNotificationService;

    @Captor
    private ArgumentCaptor<CorrelateBpmnMessageCommand> commandArgumentCaptor;

    @ParameterizedTest
    @DisplayName("Test - Continue Main Process")
    @ValueSource(booleans = {true, false})
    void testContinueMainProcess(boolean successfulCorrelation) {

        if (successfulCorrelation) {
            // Stub:
            doNothing().when(bpmnEngine).correlateMessage(any());
            // Call tested service method:
            arrivalNotificationService.continueMainProcess(MOVEMENT_ID);
            // Verification & Assertions:
            verify(bpmnEngine, times(1)).correlateMessage(commandArgumentCaptor.capture());
            assertEquals(BpmnGlobalMessageNamesEnum.TB007_MESSAGE_RECEIVED_MESSAGE.getValue(), commandArgumentCaptor.getValue().getMessageName());
            assertEquals(MOVEMENT_ID, commandArgumentCaptor.getValue().getBusinessKey());
        } else {
            // Stub:
            doThrow(new MismatchingMessageCorrelationException("ERROR")).when(bpmnEngine).correlateMessage(any());
            // Call tested service method:
            Throwable exception = assertThrows(BaseException.class, () ->
                    arrivalNotificationService.continueMainProcess(MOVEMENT_ID));
            // Assertion:
            assertEquals(ERROR_MESSAGE_PREFIX + MOVEMENT_ID + ERROR_MESSAGE_SUFFIX, exception.getMessage());
        }
    }
}
