Back to Repositories

Testing Workflow Resource Controller Implementation in Conductor-OSS

This test suite validates the WorkflowResource controller functionality in the Conductor OSS framework, focusing on RESTful API endpoints for workflow management operations. The tests ensure proper handling of workflow lifecycle operations including starting, monitoring, and controlling workflow executions.

Test Coverage Overview

The test suite provides comprehensive coverage of the WorkflowResource REST controller’s functionality.

Key areas tested include:
  • Workflow lifecycle operations (start, pause, resume, terminate)
  • Workflow status and execution monitoring
  • Search and retrieval operations
  • Error handling and edge cases
  • External storage integration

Implementation Analysis

The testing approach utilizes JUnit and Mockito frameworks for robust unit testing. The implementation follows a mock-based testing pattern, where WorkflowService and WorkflowTestService dependencies are mocked to isolate the controller layer.

Each test method focuses on a specific API endpoint, verifying both the request handling and service layer interactions.

Technical Details

Testing tools and configuration:
  • JUnit 4 for test execution
  • Mockito for service mocking
  • Mock verification for service method calls
  • setUp method with @Before annotation for test initialization
  • Argument matchers for flexible mock behavior

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Proper test isolation through mocking
  • Consistent test method naming convention
  • Single responsibility per test case
  • Thorough verification of service interactions
  • Clear test setup and initialization

conductor-oss/conductor

rest/src/test/java/com/netflix/conductor/rest/controllers/WorkflowResourceTest.java

            
/*
 * Copyright 2020 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.rest.controllers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;

import com.netflix.conductor.common.metadata.workflow.RerunWorkflowRequest;
import com.netflix.conductor.common.metadata.workflow.StartWorkflowRequest;
import com.netflix.conductor.common.run.Workflow;
import com.netflix.conductor.service.WorkflowService;
import com.netflix.conductor.service.WorkflowTestService;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class WorkflowResourceTest {

    @Mock private WorkflowService mockWorkflowService;

    @Mock private WorkflowTestService mockWorkflowTestService;

    private WorkflowResource workflowResource;

    @Before
    public void before() {
        this.mockWorkflowService = mock(WorkflowService.class);
        this.mockWorkflowTestService = mock(WorkflowTestService.class);
        this.workflowResource =
                new WorkflowResource(this.mockWorkflowService, this.mockWorkflowTestService);
    }

    @Test
    public void testStartWorkflow() {
        StartWorkflowRequest startWorkflowRequest = new StartWorkflowRequest();
        startWorkflowRequest.setName("w123");
        Map<String, Object> input = new HashMap<>();
        input.put("1", "abc");
        startWorkflowRequest.setInput(input);
        String workflowID = "w112";
        when(mockWorkflowService.startWorkflow(any(StartWorkflowRequest.class)))
                .thenReturn(workflowID);
        assertEquals("w112", workflowResource.startWorkflow(startWorkflowRequest));
    }

    @Test
    public void testStartWorkflowParam() {
        Map<String, Object> input = new HashMap<>();
        input.put("1", "abc");
        String workflowID = "w112";
        when(mockWorkflowService.startWorkflow(
                        anyString(), anyInt(), anyString(), anyInt(), anyMap()))
                .thenReturn(workflowID);
        assertEquals("w112", workflowResource.startWorkflow("test1", 1, "c123", 0, input));
    }

    @Test
    public void getWorkflows() {
        Workflow workflow = new Workflow();
        workflow.setCorrelationId("123");
        ArrayList<Workflow> listOfWorkflows =
                new ArrayList<>() {
                    {
                        add(workflow);
                    }
                };
        when(mockWorkflowService.getWorkflows(anyString(), anyString(), anyBoolean(), anyBoolean()))
                .thenReturn(listOfWorkflows);
        assertEquals(listOfWorkflows, workflowResource.getWorkflows("test1", "123", true, true));
    }

    @Test
    public void testGetWorklfowsMultipleCorrelationId() {
        Workflow workflow = new Workflow();
        workflow.setCorrelationId("c123");

        List<Workflow> workflowArrayList =
                new ArrayList<>() {
                    {
                        add(workflow);
                    }
                };

        List<String> correlationIdList =
                new ArrayList<>() {
                    {
                        add("c123");
                    }
                };

        Map<String, List<Workflow>> workflowMap = new HashMap<>();
        workflowMap.put("c123", workflowArrayList);

        when(mockWorkflowService.getWorkflows(anyString(), anyBoolean(), anyBoolean(), anyList()))
                .thenReturn(workflowMap);
        assertEquals(
                workflowMap, workflowResource.getWorkflows("test", true, true, correlationIdList));
    }

    @Test
    public void testGetExecutionStatus() {
        Workflow workflow = new Workflow();
        workflow.setCorrelationId("c123");

        when(mockWorkflowService.getExecutionStatus(anyString(), anyBoolean()))
                .thenReturn(workflow);
        assertEquals(workflow, workflowResource.getExecutionStatus("w123", true));
    }

    @Test
    public void testDelete() {
        workflowResource.delete("w123", true);
        verify(mockWorkflowService, times(1)).deleteWorkflow(anyString(), anyBoolean());
    }

    @Test
    public void testGetRunningWorkflow() {
        List<String> listOfWorklfows =
                new ArrayList<>() {
                    {
                        add("w123");
                    }
                };
        when(mockWorkflowService.getRunningWorkflows(anyString(), anyInt(), anyLong(), anyLong()))
                .thenReturn(listOfWorklfows);
        assertEquals(listOfWorklfows, workflowResource.getRunningWorkflow("w123", 1, 12L, 13L));
    }

    @Test
    public void testDecide() {
        workflowResource.decide("w123");
        verify(mockWorkflowService, times(1)).decideWorkflow(anyString());
    }

    @Test
    public void testPauseWorkflow() {
        workflowResource.pauseWorkflow("w123");
        verify(mockWorkflowService, times(1)).pauseWorkflow(anyString());
    }

    @Test
    public void testResumeWorkflow() {
        workflowResource.resumeWorkflow("test");
        verify(mockWorkflowService, times(1)).resumeWorkflow(anyString());
    }

    @Test
    public void testSkipTaskFromWorkflow() {
        workflowResource.skipTaskFromWorkflow("test", "testTask", null);
        verify(mockWorkflowService, times(1))
                .skipTaskFromWorkflow(anyString(), anyString(), isNull());
    }

    @Test
    public void testRerun() {
        RerunWorkflowRequest request = new RerunWorkflowRequest();
        workflowResource.rerun("test", request);
        verify(mockWorkflowService, times(1))
                .rerunWorkflow(anyString(), any(RerunWorkflowRequest.class));
    }

    @Test
    public void restart() {
        workflowResource.restart("w123", false);
        verify(mockWorkflowService, times(1)).restartWorkflow(anyString(), anyBoolean());
    }

    @Test
    public void testRetry() {
        workflowResource.retry("w123", false);
        verify(mockWorkflowService, times(1)).retryWorkflow(anyString(), anyBoolean());
    }

    @Test
    public void testResetWorkflow() {
        workflowResource.resetWorkflow("w123");
        verify(mockWorkflowService, times(1)).resetWorkflow(anyString());
    }

    @Test
    public void testTerminate() {
        workflowResource.terminate("w123", "test");
        verify(mockWorkflowService, times(1)).terminateWorkflow(anyString(), anyString());
    }

    @Test
    public void testTerminateRemove() {
        workflowResource.terminateRemove("w123", "test", false);
        verify(mockWorkflowService, times(1))
                .terminateRemove(anyString(), anyString(), anyBoolean());
    }

    @Test
    public void testSearch() {
        workflowResource.search(0, 100, "asc", "*", "*");
        verify(mockWorkflowService, times(1))
                .searchWorkflows(anyInt(), anyInt(), anyString(), anyString(), anyString());
    }

    @Test
    public void testSearchV2() {
        workflowResource.searchV2(0, 100, "asc", "*", "*");
        verify(mockWorkflowService).searchWorkflowsV2(0, 100, "asc", "*", "*");
    }

    @Test
    public void testSearchWorkflowsByTasks() {
        workflowResource.searchWorkflowsByTasks(0, 100, "asc", "*", "*");
        verify(mockWorkflowService, times(1))
                .searchWorkflowsByTasks(anyInt(), anyInt(), anyString(), anyString(), anyString());
    }

    @Test
    public void testSearchWorkflowsByTasksV2() {
        workflowResource.searchWorkflowsByTasksV2(0, 100, "asc", "*", "*");
        verify(mockWorkflowService).searchWorkflowsByTasksV2(0, 100, "asc", "*", "*");
    }

    @Test
    public void testGetExternalStorageLocation() {
        workflowResource.getExternalStorageLocation("path", "operation", "payloadType");
        verify(mockWorkflowService).getExternalStorageLocation("path", "operation", "payloadType");
    }
}