Back to Repositories

Testing Loan Processing Workflow Execution in conductor-oss

This test suite validates a loan processing workflow implementation in Conductor OSS, focusing on the end-to-end execution of loan calculation and approval processes. The tests verify the workflow’s ability to handle user details, credit scoring, and loan amount calculations with mock data inputs.

Test Coverage Overview

The test suite provides comprehensive coverage of a loan processing workflow, including:

  • User detail retrieval and validation
  • Credit score calculation and verification
  • Loan amount authorization logic
  • Workflow input/output data flow
  • Multi-step task sequence execution

Implementation Analysis

The testing approach utilizes JUnit framework with mock data injection for workflow validation. It implements a structured testing pattern using WorkflowTestRequest to simulate the execution environment, with careful verification of data transformation between tasks and workflow states.

The implementation leverages Conductor’s testing utilities for workflow definition loading and mock input handling.

Technical Details

Key technical components include:

  • JUnit Jupiter assertions framework
  • Conductor WorkflowTestRequest for test execution
  • JSON-based workflow definition and test input files
  • ObjectMapper for data serialization
  • Mock task outputs for isolated testing

Best Practices Demonstrated

The test exemplifies several testing best practices:

  • Systematic input/output validation at each workflow step
  • Isolation of external dependencies through mocking
  • Clear test data organization
  • Comprehensive assertion coverage
  • Structured workflow state verification

conductor-oss/conductor

client/src/test/java/com/netflix/conductor/client/testing/LoanWorkflowTest.java

            
/*
 * Copyright 2023 Conductor Authors.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package com.netflix.conductor.client.testing;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import com.netflix.conductor.common.metadata.tasks.Task;
import com.netflix.conductor.common.metadata.workflow.WorkflowDef;
import com.netflix.conductor.common.run.Workflow;
import com.netflix.conductor.common.run.WorkflowTestRequest;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

/** Unit test a workflow with inputs read from a file. */
public class LoanWorkflowTest extends AbstractWorkflowTests {

    /** Uses mock inputs to verify the workflow execution and input/outputs of the tasks */
    // Tests are commented out since it requires a running server
    // @Test
    public void verifyWorkflowExecutionWithMockInputs() throws IOException {
        WorkflowDef def = getWorkflowDef("/workflows/calculate_loan_workflow.json");
        assertNotNull(def);
        Map<String, List<WorkflowTestRequest.TaskMock>> testInputs =
                getTestInputs("/test_data/loan_workflow_input.json");
        assertNotNull(testInputs);

        WorkflowTestRequest testRequest = new WorkflowTestRequest();
        testRequest.setWorkflowDef(def);

        LoanWorkflowInput workflowInput = new LoanWorkflowInput();
        workflowInput.setUserEmail("[email protected]");
        workflowInput.setLoanAmount(new BigDecimal(11_000));
        testRequest.setInput(objectMapper.convertValue(workflowInput, Map.class));

        testRequest.setTaskRefToMockOutput(testInputs);
        testRequest.setName(def.getName());
        testRequest.setVersion(def.getVersion());

        Workflow execution = workflowClient.testWorkflow(testRequest);
        assertNotNull(execution);

        // Assert that the workflow completed successfully
        assertEquals(Workflow.WorkflowStatus.COMPLETED, execution.getStatus());

        // Ensure the inputs were captured correctly
        assertEquals(
                workflowInput.getLoanAmount().toString(),
                String.valueOf(execution.getInput().get("loanAmount")));
        assertEquals(workflowInput.getUserEmail(), execution.getInput().get("userEmail"));

        // A total of 3 tasks were executed
        assertEquals(3, execution.getTasks().size());

        Task fetchUserDetails = execution.getTasks().get(0);
        Task getCreditScore = execution.getTasks().get(1);
        Task calculateLoanAmount = execution.getTasks().get(2);

        // fetch user details received the correct input from the workflow
        assertEquals(
                workflowInput.getUserEmail(), fetchUserDetails.getInputData().get("userEmail"));

        // And that the task produced the right output
        int userAccountNo = 12345;
        assertEquals(userAccountNo, fetchUserDetails.getOutputData().get("userAccount"));

        // get credit score received the right account number from the output of the fetch user
        // details
        assertEquals(userAccountNo, getCreditScore.getInputData().get("userAccountNumber"));
        int expectedCreditRating = 750;

        // The task produced the right output
        assertEquals(expectedCreditRating, getCreditScore.getOutputData().get("creditRating"));

        // Calculate loan amount gets the right loan amount from workflow input
        assertEquals(
                workflowInput.getLoanAmount().toString(),
                String.valueOf(calculateLoanAmount.getInputData().get("loanAmount")));

        // Calculate loan amount gets the right credit rating from the previous task
        assertEquals(expectedCreditRating, calculateLoanAmount.getInputData().get("creditRating"));

        int authorizedLoanAmount = 10_000;
        assertEquals(
                authorizedLoanAmount,
                calculateLoanAmount.getOutputData().get("authorizedLoanAmount"));

        // Finally, lets verify the workflow outputs
        assertEquals(userAccountNo, execution.getOutput().get("accountNumber"));
        assertEquals(expectedCreditRating, execution.getOutput().get("creditRating"));
        assertEquals(authorizedLoanAmount, execution.getOutput().get("authorizedLoanAmount"));

        System.out.println(execution);
    }
}