Skip to content

Commit a59a23c

Browse files
authored
Add unit tests for wrapper calls (#974)
* Add unit tests for wrapper calls
1 parent c39c4c5 commit a59a23c

File tree

2 files changed

+145
-15
lines changed

2 files changed

+145
-15
lines changed

src/main/java/com/uber/cadence/internal/sync/TestActivityEnvironmentInternal.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -621,8 +621,7 @@ public void RestartWorkflowExecution(
621621

622622
@Override
623623
public void GetTaskListsByDomain(
624-
GetTaskListsByDomainRequest request, AsyncMethodCallback resultHandler)
625-
throws org.apache.thrift.TException {
624+
GetTaskListsByDomainRequest request, AsyncMethodCallback resultHandler) throws TException {
626625
impl.GetTaskListsByDomain(request, resultHandler);
627626
}
628627

@@ -893,16 +892,22 @@ public void DescribeTaskList(DescribeTaskListRequest request, AsyncMethodCallbac
893892
}
894893

895894
@Override
896-
public void GetClusterInfo(AsyncMethodCallback resultHandler) throws TException {}
895+
public void GetClusterInfo(AsyncMethodCallback resultHandler) throws TException {
896+
impl.GetClusterInfo(resultHandler);
897+
}
897898

898899
@Override
899900
public void ListTaskListPartitions(
900901
ListTaskListPartitionsRequest request, AsyncMethodCallback resultHandler)
901-
throws TException {}
902+
throws TException {
903+
impl.ListTaskListPartitions(request, resultHandler);
904+
}
902905

903906
@Override
904907
public void RefreshWorkflowTasks(
905-
RefreshWorkflowTasksRequest request, AsyncMethodCallback resultHandler) throws TException {}
908+
RefreshWorkflowTasksRequest request, AsyncMethodCallback resultHandler) throws TException {
909+
impl.RefreshWorkflowTasks(request, resultHandler);
910+
}
906911

907912
@Override
908913
public void RegisterDomain(RegisterDomainRequest registerRequest)

src/test/java/com/uber/cadence/internal/sync/TestActivityEnvironmentInternalTest.java

Lines changed: 135 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Modifications copyright (C) 2017 Uber Technologies, Inc.
1818
package com.uber.cadence.internal.sync;
1919

2020
import static org.junit.Assert.fail;
21+
import static org.mockito.Mockito.*;
2122
import static org.mockito.Mockito.mock;
2223

2324
import com.uber.cadence.WorkflowExecution;
@@ -28,8 +29,7 @@ Modifications copyright (C) 2017 Uber Technologies, Inc.
2829
import java.lang.reflect.Method;
2930
import java.lang.reflect.Type;
3031
import java.time.Duration;
31-
import java.util.Map;
32-
import java.util.Optional;
32+
import java.util.*;
3333
import java.util.function.BiPredicate;
3434
import java.util.function.Supplier;
3535
import org.junit.Before;
@@ -44,6 +44,8 @@ public class TestActivityEnvironmentInternalTest {
4444

4545
private Object testActivityExecutor;
4646

47+
private Object testWorkflowServiceWrapper;
48+
4749
// Helper method to find the inner class
4850
private Class<?> findTestActivityExecutorClass() {
4951
for (Class<?> declaredClass : TestActivityEnvironmentInternal.class.getDeclaredClasses()) {
@@ -54,18 +56,26 @@ private Class<?> findTestActivityExecutorClass() {
5456
throw new RuntimeException("Could not find TestActivityExecutor inner class");
5557
}
5658

57-
// Helper method to print all methods
58-
private void printMethods(Class<?> clazz) {
59-
System.out.println("Methods for " + clazz.getName() + ":");
60-
for (Method method : clazz.getDeclaredMethods()) {
61-
System.out.println(" " + method);
59+
// Helper method to find the inner class
60+
private Class<?> findWorkflowServiceWrapperClass() {
61+
for (Class<?> declaredClass : TestActivityEnvironmentInternal.class.getDeclaredClasses()) {
62+
if (declaredClass.getSimpleName().equals("WorkflowServiceWrapper")) {
63+
return declaredClass;
64+
}
6265
}
66+
throw new RuntimeException("Could not find WorkflowServiceWrapper inner class");
6367
}
6468

6569
@Before
6670
public void setUp() {
6771
MockitoAnnotations.openMocks(this);
6872

73+
setupActivityExecutor();
74+
75+
setupWorkflowServiceWrapper();
76+
}
77+
78+
private void setupActivityExecutor() {
6979
try {
7080
// Find the inner class first
7181
Class<?> innerClass = findTestActivityExecutorClass();
@@ -83,16 +93,63 @@ public void setUp() {
8393

8494
// Create the instance
8595
testActivityExecutor = constructor.newInstance(outerInstance, mockWorkflowService, mockNext);
96+
} catch (Exception e) {
97+
e.printStackTrace();
98+
throw new RuntimeException("Failed to set up test: " + e.getMessage(), e);
99+
}
100+
}
86101

87-
// Debug print the class and methods
88-
System.out.println("TestActivityExecutor class: " + innerClass);
89-
printMethods(innerClass);
102+
private void setupWorkflowServiceWrapper() {
103+
try {
104+
// Find the inner class first
105+
Class<?> innerClass = findWorkflowServiceWrapperClass();
106+
107+
// Get the constructor with the specific parameter types
108+
Constructor<?> constructor =
109+
innerClass.getDeclaredConstructor(
110+
TestActivityEnvironmentInternal.class, IWorkflowService.class);
111+
constructor.setAccessible(true);
112+
113+
// Create an instance of the outer class
114+
TestActivityEnvironmentInternal outerInstance = mock(TestActivityEnvironmentInternal.class);
115+
116+
// Create the instance
117+
testWorkflowServiceWrapper = constructor.newInstance(outerInstance, mockWorkflowService);
90118
} catch (Exception e) {
91119
e.printStackTrace();
92120
throw new RuntimeException("Failed to set up test: " + e.getMessage(), e);
93121
}
94122
}
95123

124+
@Test
125+
public void testWorkflowServiceWrapperMethodDelegation() throws Exception {
126+
// Prepare test cases
127+
List<MethodTestCase> testCases = prepareMethodTestCases();
128+
129+
System.out.println(testCases);
130+
131+
// Test each method
132+
for (MethodTestCase testCase : testCases) {
133+
try {
134+
// Find the method on the wrapper
135+
Method wrapperMethod =
136+
testWorkflowServiceWrapper
137+
.getClass()
138+
.getMethod(testCase.methodName, testCase.parameterTypes);
139+
140+
// Invoke the method on the wrapper
141+
wrapperMethod.invoke(testWorkflowServiceWrapper, testCase.arguments);
142+
143+
// Generic verification using reflection
144+
verifyMethodInvocation(mockWorkflowService, testCase);
145+
146+
} catch (Exception e) {
147+
// Rethrow to fail the test if any unexpected exception occurs
148+
throw new AssertionError("Failed to test method: " + testCase.methodName, e);
149+
}
150+
}
151+
}
152+
96153
@Test
97154
public void testAllMethodsThrowUnsupportedOperationException() throws Exception {
98155
// Define test cases for different methods
@@ -232,4 +289,72 @@ private static class MethodTestCase {
232289
this.arguments = arguments;
233290
}
234291
}
292+
293+
/** Generic method to verify method invocation on mock */
294+
private void verifyMethodInvocation(Object mockObject, MethodTestCase testCase) throws Exception {
295+
// Use Mockito's verify with reflection
296+
if (testCase.arguments.length == 0) {
297+
// For methods with no arguments
298+
verify(mockObject).getClass().getMethod(testCase.methodName).invoke(mockObject);
299+
} else {
300+
// For methods with arguments
301+
Method verifyMethod = org.mockito.Mockito.class.getMethod("verify", Object.class);
302+
Object verifiedMock = verifyMethod.invoke(null, mockObject);
303+
304+
// Invoke the method on the verified mock
305+
verifiedMock
306+
.getClass()
307+
.getMethod(testCase.methodName, testCase.parameterTypes)
308+
.invoke(verifiedMock, testCase.arguments);
309+
}
310+
}
311+
312+
/** Prepares test cases for all methods in IWorkflowService */
313+
private List<MethodTestCase> prepareMethodTestCases() throws Exception {
314+
List<MethodTestCase> testCases = new ArrayList<>();
315+
316+
// You can add more methods here as needed
317+
// Dynamically discover and add more methods from IWorkflowService if required
318+
Method[] allMethods = IWorkflowService.class.getMethods();
319+
for (Method method : allMethods) {
320+
testCases.add(createDefaultMethodTestCase(method));
321+
}
322+
return testCases;
323+
}
324+
325+
/** Creates a default MethodTestCase for a given method */
326+
private MethodTestCase createDefaultMethodTestCase(Method method) throws Exception {
327+
Class<?>[] parameterTypes = method.getParameterTypes();
328+
Object[] arguments = new Object[parameterTypes.length];
329+
330+
for (int i = 0; i < parameterTypes.length; i++) {
331+
arguments[i] = createDefaultArgument(parameterTypes[i]);
332+
}
333+
334+
return new MethodTestCase(method.getName(), parameterTypes, arguments);
335+
}
336+
337+
/** Creates a default argument for different parameter types */
338+
private Object createDefaultArgument(Class<?> type) throws Exception {
339+
if (type.isPrimitive()) {
340+
if (type == boolean.class) return false;
341+
if (type == char.class) return '\u0000';
342+
if (type == byte.class) return (byte) 0;
343+
if (type == short.class) return (short) 0;
344+
if (type == int.class) return 0;
345+
if (type == long.class) return 0L;
346+
if (type == float.class) return 0.0f;
347+
if (type == double.class) return 0.0d;
348+
}
349+
350+
// For non-primitive types, try to create an empty instance
351+
if (type.getConstructors().length > 0
352+
&& Arrays.stream(type.getConstructors())
353+
.anyMatch(constructor -> constructor.getParameterCount() == 0)) {
354+
return type.getDeclaredConstructor().newInstance();
355+
}
356+
357+
// Fallback for complex types
358+
return null;
359+
}
235360
}

0 commit comments

Comments
 (0)