Skip to content

Commit a743f37

Browse files
515 - integration tests for on-error dispatcher
1 parent 5e592b9 commit a743f37

File tree

6 files changed

+404
-0
lines changed

6 files changed

+404
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* Copyright 2025 ByteChef
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.bytechef.task.dispatcher.on.error;
18+
19+
import com.bytechef.atlas.coordinator.task.completion.TaskCompletionHandlerFactory;
20+
import com.bytechef.atlas.coordinator.task.dispatcher.TaskDispatcherResolverFactory;
21+
import com.bytechef.atlas.execution.service.ContextService;
22+
import com.bytechef.atlas.execution.service.CounterService;
23+
import com.bytechef.atlas.execution.service.TaskExecutionService;
24+
import com.bytechef.atlas.file.storage.TaskFileStorage;
25+
import com.bytechef.atlas.worker.exception.TaskExecutionException;
26+
import com.bytechef.atlas.worker.task.handler.TaskHandler;
27+
import com.bytechef.commons.util.EncodingUtils;
28+
import com.bytechef.evaluator.SpelEvaluator;
29+
import com.bytechef.exception.ExecutionException;
30+
import com.bytechef.platform.workflow.task.dispatcher.test.annotation.TaskDispatcherIntTest;
31+
import com.bytechef.platform.workflow.task.dispatcher.test.task.handler.TestVarTaskHandler;
32+
import com.bytechef.platform.workflow.task.dispatcher.test.workflow.TaskDispatcherJobTestExecutor;
33+
import com.bytechef.task.dispatcher.loop.LoopTaskDispatcher;
34+
import com.bytechef.task.dispatcher.loop.completion.LoopTaskCompletionHandler;
35+
import com.bytechef.task.dispatcher.on.error.completition.OnErrorTaskCompletionHandler;
36+
import java.nio.charset.StandardCharsets;
37+
import java.util.Collections;
38+
import java.util.List;
39+
import java.util.Map;
40+
import org.junit.jupiter.api.Assertions;
41+
import org.junit.jupiter.api.BeforeEach;
42+
import org.junit.jupiter.api.Test;
43+
import org.springframework.beans.factory.annotation.Autowired;
44+
import org.springframework.context.ApplicationEventPublisher;
45+
46+
/**
47+
* @author Matija Petanjek
48+
*/
49+
@TaskDispatcherIntTest
50+
public class OnErrorTaskDispatcherIntTest {
51+
52+
private TestVarTaskHandler<Object, Object> testVarTaskHandler;
53+
54+
@Autowired
55+
protected ContextService contextService;
56+
57+
@Autowired
58+
protected TaskExecutionService taskExecutionService;
59+
60+
@Autowired
61+
private TaskDispatcherJobTestExecutor taskDispatcherJobTestExecutor;
62+
63+
@Autowired
64+
private TaskFileStorage taskFileStorage;
65+
66+
@BeforeEach
67+
void beforeEach() {
68+
testVarTaskHandler = new TestVarTaskHandler<>(Map::put);
69+
}
70+
71+
@Test
72+
public void testOnErrorTaskDispatcherWhenNoException() {
73+
taskDispatcherJobTestExecutor.execute(
74+
EncodingUtils.base64EncodeToString("on-error_v1-no-exception".getBytes(StandardCharsets.UTF_8)),
75+
Collections.emptyMap(),
76+
this::getTaskCompletionHandlerFactories,
77+
this::getTaskDispatcherResolverFactories,
78+
this::getTaskHandlerMap);
79+
80+
Assertions.assertEquals("main branch", testVarTaskHandler.get("mainBranchVar"));
81+
Assertions.assertNull(testVarTaskHandler.get("errorBranchVar"));
82+
Assertions.assertEquals("end", testVarTaskHandler.get("endVar"));
83+
}
84+
85+
@Test
86+
public void testOnErrorTaskDispatcherWhenExceptionInMainBranch() {
87+
taskDispatcherJobTestExecutor.execute(
88+
EncodingUtils.base64EncodeToString("on-error_v1-exception-main-branch".getBytes(StandardCharsets.UTF_8)),
89+
Collections.emptyMap(),
90+
this::getTaskCompletionHandlerFactories,
91+
this::getTaskDispatcherResolverFactories,
92+
this::getTaskHandlerMap);
93+
94+
Assertions.assertEquals(
95+
"main branch before exception", testVarTaskHandler.get("beforeExceptionMainBranchVar"));
96+
Assertions.assertNull(testVarTaskHandler.get("afterExceptionMainBranchVar"));
97+
Assertions.assertEquals("error branch", testVarTaskHandler.get("errorBranchVar"));
98+
Assertions.assertEquals("end", testVarTaskHandler.get("endVar"));
99+
}
100+
101+
@Test
102+
public void testOnErrorTaskDispatcherWhenExceptionInOnErrorBranch() {
103+
ExecutionException executionException = Assertions.assertThrows(
104+
ExecutionException.class, () -> taskDispatcherJobTestExecutor.execute(
105+
EncodingUtils
106+
.base64EncodeToString("on-error_v1-exception-error-branch".getBytes(StandardCharsets.UTF_8)),
107+
Collections.emptyMap(),
108+
this::getTaskCompletionHandlerFactories,
109+
this::getTaskDispatcherResolverFactories,
110+
this::getTaskHandlerMap));
111+
112+
Assertions.assertEquals("test exception", executionException.getMessage());
113+
114+
Assertions.assertEquals("main branch", testVarTaskHandler.get("mainBranchVar"));
115+
Assertions.assertEquals(
116+
"before exception in error branch", testVarTaskHandler.get("beforeExceptionErrorBranchVar"));
117+
Assertions.assertNull(testVarTaskHandler.get("afterExceptionErrorBranchVar"));
118+
Assertions.assertNull(testVarTaskHandler.get("endVar"));
119+
}
120+
121+
@Test
122+
public void testOnErrorTaskDispatcherInLoopTaskDispatcherWhenExceptionInMainBranch() {
123+
taskDispatcherJobTestExecutor.execute(
124+
EncodingUtils
125+
.base64EncodeToString("on-error_v1-exception-main-branch-in-loop_v1".getBytes(StandardCharsets.UTF_8)),
126+
Collections.emptyMap(),
127+
this::getTaskCompletionHandlerFactories,
128+
this::getTaskDispatcherResolverFactories,
129+
this::getTaskHandlerMap);
130+
131+
Assertions.assertEquals(
132+
"main branch before exception, iteration number 2",
133+
testVarTaskHandler.get("beforeExceptionMainBranchVar"));
134+
Assertions.assertNull(testVarTaskHandler.get("afterExceptionMainBranchVar"));
135+
Assertions.assertEquals("error branch iteration number 2", testVarTaskHandler.get("errorBranchVar"));
136+
Assertions.assertEquals("end", testVarTaskHandler.get("endVar"));
137+
}
138+
139+
@Test
140+
public void testOnErrorTaskDispatcherInLoopTaskDispatcherWhenExceptionInErrorBranch() {
141+
ExecutionException executionException = Assertions.assertThrows(
142+
ExecutionException.class, () -> taskDispatcherJobTestExecutor.execute(
143+
EncodingUtils.base64EncodeToString(
144+
"on-error_v1-exception-error-branch-in-loop_v1".getBytes(StandardCharsets.UTF_8)),
145+
Collections.emptyMap(),
146+
this::getTaskCompletionHandlerFactories,
147+
this::getTaskDispatcherResolverFactories,
148+
this::getTaskHandlerMap));
149+
150+
Assertions.assertEquals("test exception", executionException.getMessage());
151+
152+
Assertions.assertEquals(
153+
"main branch before exception, iteration number 1",
154+
testVarTaskHandler.get("beforeExceptionMainBranchVar"));
155+
Assertions.assertNull(testVarTaskHandler.get("afterExceptionMainBranchVar"));
156+
Assertions.assertEquals(
157+
"error branch before exception, iteration number 1",
158+
testVarTaskHandler.get("beforeExceptionErrorBranchVar"));
159+
Assertions.assertNull(testVarTaskHandler.get("afterExceptionErrorBranchVar"));
160+
Assertions.assertNull(testVarTaskHandler.get("endVar"));
161+
}
162+
163+
@SuppressWarnings("PMD")
164+
private List<TaskCompletionHandlerFactory> getTaskCompletionHandlerFactories(
165+
CounterService counterService, TaskExecutionService taskExecutionService) {
166+
167+
return List.of(
168+
(taskCompletionHandler, taskDispatcher) -> new LoopTaskCompletionHandler(
169+
contextService, SpelEvaluator.create(), taskCompletionHandler, taskDispatcher, taskExecutionService,
170+
taskFileStorage),
171+
(taskCompletionHandler, taskDispatcher) -> new OnErrorTaskCompletionHandler(
172+
contextService, SpelEvaluator.create(), taskCompletionHandler, taskDispatcher, taskExecutionService,
173+
taskFileStorage));
174+
}
175+
176+
@SuppressWarnings("PMD")
177+
private List<TaskDispatcherResolverFactory> getTaskDispatcherResolverFactories(
178+
ApplicationEventPublisher eventPublisher, ContextService contextService,
179+
CounterService counterService, TaskExecutionService taskExecutionService) {
180+
181+
return List.of((taskDispatcher) -> new LoopTaskDispatcher(
182+
contextService, SpelEvaluator.create(), eventPublisher, taskDispatcher, taskExecutionService,
183+
taskFileStorage),
184+
(taskDispatcher) -> new OnErrorTaskDispatcher(
185+
contextService, SpelEvaluator.create(), eventPublisher, taskDispatcher, taskExecutionService,
186+
taskFileStorage));
187+
}
188+
189+
private Map<String, TaskHandler<?>> getTaskHandlerMap() {
190+
return Map.of(
191+
"var/v1/set", testVarTaskHandler,
192+
"httpClient/v1/get", taskExecution -> {
193+
throw new TaskExecutionException("test exception");
194+
});
195+
}
196+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
label: "On Error Task Dispatcher"
3+
tasks:
4+
- name: "loop_1"
5+
type: "loop/v1"
6+
parameters:
7+
loopForever: false
8+
items:
9+
- 1
10+
- 2
11+
iteratee:
12+
- name: "on_error_1"
13+
type: "on-error/v1"
14+
parameters:
15+
main-branch:
16+
- name: "beforeExceptionMainBranchVar"
17+
type: "var/v1/set"
18+
parameters:
19+
value: "main branch before exception, iteration number ${loop_1.item}"
20+
- name: "httpClient_error"
21+
type: "httpClient/v1/get"
22+
parameters:
23+
allowUnauthorizedCerts: false
24+
responseType: "JSON"
25+
responseContentType: "application/octet-stream"
26+
fullResponse: false
27+
followAllRedirects: false
28+
followRedirect: false
29+
ignoreResponseCode: false
30+
timeout: 1000
31+
uri: "https://localhost:8080"
32+
- name: "afterExceptionMainBranchVar"
33+
type: "var/v1/set"
34+
parameters:
35+
value: "main branch after exception, iteration number ${loop_1.item}"
36+
on-error-branch:
37+
- name: "beforeExceptionErrorBranchVar"
38+
type: "var/v1/set"
39+
parameters:
40+
value: "error branch before exception, iteration number ${loop_1.item}"
41+
- name: "httpClient_error"
42+
type: "httpClient/v1/get"
43+
parameters:
44+
allowUnauthorizedCerts: false
45+
responseType: "JSON"
46+
responseContentType: "application/octet-stream"
47+
fullResponse: false
48+
followAllRedirects: false
49+
followRedirect: false
50+
ignoreResponseCode: false
51+
timeout: 1000
52+
uri: "https://localhost:8080"
53+
- name: "afterExceptionErrorBranchVar"
54+
type: "var/v1/set"
55+
parameters:
56+
value: "error branch after exception, iteration number ${loop_1.item}"
57+
- name: "endVar"
58+
type: "var/v1/set"
59+
parameters:
60+
value: "end"
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
label: "On Error Task Dispatcher"
3+
tasks:
4+
- name: "on_error_1"
5+
type: "on-error/v1"
6+
parameters:
7+
main-branch:
8+
- name: "mainBranchVar"
9+
type: "var/v1/set"
10+
parameters:
11+
value: "main branch"
12+
- name: "httpClient_error_1"
13+
type: "httpClient/v1/get"
14+
parameters:
15+
allowUnauthorizedCerts: false
16+
responseType: "JSON"
17+
responseContentType: "application/octet-stream"
18+
fullResponse: false
19+
followAllRedirects: false
20+
followRedirect: false
21+
ignoreResponseCode: false
22+
timeout: 1000
23+
uri: "https://localhost:8080"
24+
on-error-branch:
25+
- name: "beforeExceptionErrorBranchVar"
26+
type: "var/v1/set"
27+
parameters:
28+
value: "before exception in error branch"
29+
- name: "httpClient_error_2"
30+
type: "httpClient/v1/get"
31+
parameters:
32+
allowUnauthorizedCerts: false
33+
responseType: "JSON"
34+
responseContentType: "application/octet-stream"
35+
fullResponse: false
36+
followAllRedirects: false
37+
followRedirect: false
38+
ignoreResponseCode: false
39+
timeout: 1000
40+
uri: "https://localhost:8080"
41+
- name: "afterExceptionErrorBranchVar"
42+
type: "var/v1/set"
43+
parameters:
44+
value: "you should not see this"
45+
- name: "endVar"
46+
type: "var/v1/set"
47+
parameters:
48+
value: "end"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
label: "On Error Task Dispatcher"
3+
tasks:
4+
- name: "loop_1"
5+
type: "loop/v1"
6+
parameters:
7+
loopForever: false
8+
items:
9+
- 1
10+
- 2
11+
iteratee:
12+
- name: "on_error_1"
13+
type: "on-error/v1"
14+
parameters:
15+
main-branch:
16+
- name: "beforeExceptionMainBranchVar"
17+
type: "var/v1/set"
18+
parameters:
19+
value: "main branch before exception, iteration number ${loop_1.item}"
20+
- name: "httpClient_error"
21+
type: "httpClient/v1/get"
22+
parameters:
23+
allowUnauthorizedCerts: false
24+
responseType: "JSON"
25+
responseContentType: "application/octet-stream"
26+
fullResponse: false
27+
followAllRedirects: false
28+
followRedirect: false
29+
ignoreResponseCode: false
30+
timeout: 1000
31+
uri: "https://localhost:8080"
32+
- name: "afterExceptionMainBranchVar"
33+
type: "var/v1/set"
34+
parameters:
35+
value: "main branch after exception, iteration number ${loop_1.item}"
36+
on-error-branch:
37+
- name: "errorBranchVar"
38+
type: "var/v1/set"
39+
parameters:
40+
value: "error branch iteration number ${loop_1.item}"
41+
- name: "endVar"
42+
type: "var/v1/set"
43+
parameters:
44+
value: "end"
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
label: "On Error Task Dispatcher"
3+
tasks:
4+
- name: "on_error_1"
5+
type: "on-error/v1"
6+
parameters:
7+
main-branch:
8+
- name: "beforeExceptionMainBranchVar"
9+
type: "var/v1/set"
10+
parameters:
11+
value: "main branch before exception"
12+
- name: "httpClient_error"
13+
type: "httpClient/v1/get"
14+
parameters:
15+
allowUnauthorizedCerts: false
16+
responseType: "JSON"
17+
responseContentType: "application/octet-stream"
18+
fullResponse: false
19+
followAllRedirects: false
20+
followRedirect: false
21+
ignoreResponseCode: false
22+
timeout: 1000
23+
uri: "https://localhost:8080"
24+
- name: "afterExceptionMainBranchVar"
25+
type: "var/v1/set"
26+
parameters:
27+
value: "main branch after exception"
28+
on-error-branch:
29+
- name: "errorBranchVar"
30+
type: "var/v1/set"
31+
parameters:
32+
value: "error branch"
33+
- name: "endVar"
34+
type: "var/v1/set"
35+
parameters:
36+
value: "end"

0 commit comments

Comments
 (0)