Skip to content

Commit 6a01ee5

Browse files
committed
Testing
1 parent 21dc657 commit 6a01ee5

23 files changed

+2332
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package io.github.vishalmysore.a2a.server;
2+
3+
import java.util.List;
4+
5+
/**
6+
* Interface for providing actions for agent cards.
7+
*/
8+
public interface ActionProvider {
9+
10+
/**
11+
* Gets a list of actions that can be performed.
12+
*
13+
* @return A list of actions.
14+
*/
15+
Object getActionList();
16+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package io.github.vishalmysore.a2a.server;
2+
3+
import io.github.vishalmysore.a2a.domain.AgentCard;
4+
import io.github.vishalmysore.a2a.domain.Artifact;
5+
6+
import java.util.ArrayList;
7+
import java.util.List;
8+
import java.util.Map;
9+
10+
/**
11+
* DynamicAgentCardController for testing.
12+
* This implementation is separate from the main DynamicAgentCardController
13+
* and is specifically for unit testing with the ActionProvider.
14+
*/
15+
public class TestDynamicAgentCardController {
16+
17+
private ActionProvider actionProvider;
18+
19+
public TestDynamicAgentCardController(ActionProvider actionProvider) {
20+
this.actionProvider = actionProvider;
21+
}
22+
23+
/**
24+
* Gets an agent card for the specified agent.
25+
*
26+
* @param agentName The name of the agent.
27+
* @return The agent card with actions.
28+
*/
29+
public AgentCard getAgentCard(String agentName) {
30+
AgentCard agentCard = new AgentCard();
31+
agentCard.setName("Test Agent");
32+
33+
Object actionListObj = actionProvider.getActionList();
34+
List<Artifact> actions = new ArrayList<>();
35+
36+
// Convert action list items to Artifacts
37+
if (actionListObj instanceof List) {
38+
List<?> actionList = (List<?>) actionListObj;
39+
for (Object action : actionList) {
40+
if (action instanceof Map) {
41+
Map<?, ?> actionMap = (Map<?, ?>) action;
42+
Artifact artifact = new Artifact();
43+
artifact.setName(actionMap.get("title").toString());
44+
artifact.setDescription(actionMap.get("description").toString());
45+
actions.add(artifact);
46+
}
47+
}
48+
}
49+
50+
return agentCard;
51+
}
52+
}
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
package io.github.vishalmysore.a2a.client;
2+
3+
import io.github.vishalmysore.a2a.domain.*;
4+
import io.github.vishalmysore.common.AgentInfo;
5+
import io.github.vishalmysore.common.CommonClientResponse;
6+
import org.junit.jupiter.api.BeforeEach;
7+
import org.junit.jupiter.api.Test;
8+
import org.mockito.MockedStatic;
9+
import org.springframework.http.HttpStatus;
10+
import org.springframework.http.ResponseEntity;
11+
import org.springframework.web.client.HttpClientErrorException;
12+
import org.springframework.web.client.RestTemplate;
13+
14+
import java.io.ByteArrayInputStream;
15+
import java.io.IOException;
16+
import java.net.HttpURLConnection;
17+
import java.net.URL;
18+
import java.util.UUID;
19+
20+
import static org.junit.jupiter.api.Assertions.*;
21+
import static org.mockito.ArgumentMatchers.any;
22+
import static org.mockito.ArgumentMatchers.eq;
23+
import static org.mockito.Mockito.*;
24+
25+
class A2AAgentTest {
26+
27+
private A2AAgent a2aAgent;
28+
private RestTemplate mockRestTemplate;
29+
private HttpURLConnection mockConnection;
30+
31+
@BeforeEach
32+
void setUp() {
33+
a2aAgent = new A2AAgent();
34+
mockRestTemplate = mock(RestTemplate.class);
35+
mockConnection = mock(HttpURLConnection.class);
36+
}
37+
38+
@Test
39+
void testGetType() {
40+
assertEquals("a2a", a2aAgent.getType());
41+
}
42+
43+
@Test
44+
void testRemoteMethodCall() throws Exception {
45+
// Setup
46+
String query = "Test query";
47+
SendTaskResponse mockResponse = new SendTaskResponse();
48+
Task task = new Task();
49+
task.setId(UUID.randomUUID().toString());
50+
mockResponse.setResult(task);
51+
52+
// Use MockedStatic for RestTemplate
53+
try (MockedStatic<UUID> mockedUuid = mockStatic(UUID.class)) {
54+
UUID mockUuid = mock(UUID.class);
55+
when(mockUuid.toString()).thenReturn("test-uuid");
56+
mockedUuid.when(UUID::randomUUID).thenReturn(mockUuid);
57+
58+
// Setup the URL
59+
a2aAgent.connect("http://test-url/.well-known/agent.json", null);
60+
61+
// Mock RestTemplate
62+
mockRestTemplate = mock(RestTemplate.class);
63+
when(mockRestTemplate.postForEntity(
64+
anyString(),
65+
any(),
66+
eq(SendTaskResponse.class)
67+
)).thenReturn(new ResponseEntity<>(mockResponse, HttpStatus.OK));
68+
69+
// Use reflection to replace the RestTemplate with our mock
70+
// (can't directly set it since A2AAgent creates a new instance each call)
71+
try (MockedStatic<RestTemplate> mockedRestTemplate = mockStatic(RestTemplate.class)) {
72+
mockedRestTemplate.when(RestTemplate::new).thenReturn(mockRestTemplate);
73+
74+
// Execute
75+
CommonClientResponse response = a2aAgent.remoteMethodCall(query);
76+
77+
// Verify
78+
assertNotNull(response);
79+
assertEquals(mockResponse, response);
80+
}
81+
}
82+
}
83+
84+
@Test
85+
void testRemoteMethodCallWithName() throws Exception {
86+
// Setup
87+
String query = "Test query";
88+
String methodName = "test-method";
89+
SendTaskResponse mockResponse = new SendTaskResponse();
90+
Task task = new Task();
91+
task.setId(UUID.randomUUID().toString());
92+
mockResponse.setResult(task);
93+
94+
// Use MockedStatic for RestTemplate
95+
try (MockedStatic<UUID> mockedUuid = mockStatic(UUID.class)) {
96+
UUID mockUuid = mock(UUID.class);
97+
when(mockUuid.toString()).thenReturn("test-uuid");
98+
mockedUuid.when(UUID::randomUUID).thenReturn(mockUuid);
99+
100+
// Setup the URL
101+
a2aAgent.connect("http://test-url/.well-known/agent.json", null);
102+
103+
// Mock RestTemplate
104+
mockRestTemplate = mock(RestTemplate.class);
105+
when(mockRestTemplate.postForEntity(
106+
anyString(),
107+
any(),
108+
eq(SendTaskResponse.class)
109+
)).thenReturn(new ResponseEntity<>(mockResponse, HttpStatus.OK));
110+
111+
// Use reflection to replace the RestTemplate with our mock
112+
try (MockedStatic<RestTemplate> mockedRestTemplate = mockStatic(RestTemplate.class)) {
113+
mockedRestTemplate.when(RestTemplate::new).thenReturn(mockRestTemplate);
114+
115+
// Execute
116+
CommonClientResponse response = a2aAgent.remoteMethodCall(methodName, query);
117+
118+
// Verify
119+
assertNotNull(response);
120+
assertEquals(mockResponse, response);
121+
}
122+
}
123+
}
124+
125+
@Test
126+
void testConnectAndDisconnect() throws Exception {
127+
// Setup for connect
128+
String agentCardJson = "{\"name\":\"Test Agent\",\"description\":\"Test Description\",\"agent_type\":\"a2a\"}";
129+
130+
// Mock URL and connection
131+
URL mockUrl = mock(URL.class);
132+
try (MockedStatic<URL> mockedUrl = mockStatic(URL.class)) {
133+
mockedUrl.when(() -> new URL(anyString())).thenReturn(mockUrl);
134+
when(mockUrl.openConnection()).thenReturn(mockConnection);
135+
when(mockConnection.getInputStream()).thenReturn(new ByteArrayInputStream(agentCardJson.getBytes()));
136+
when(mockConnection.getResponseCode()).thenReturn(200);
137+
138+
// Execute connect
139+
a2aAgent.connect("http://test-url/.well-known/agent.json", null);
140+
141+
// Verify connect
142+
assertTrue(a2aAgent.isConnected());
143+
AgentCard agentCard = (AgentCard) a2aAgent.getInfo();
144+
assertEquals("Test Agent", agentCard.getName());
145+
assertEquals("Test Description", agentCard.getDescription());
146+
147+
// Execute disconnect
148+
a2aAgent.disconnect();
149+
150+
// Verify disconnect
151+
assertFalse(a2aAgent.isConnected());
152+
assertNull(a2aAgent.getInfo());
153+
}
154+
}
155+
156+
@Test
157+
void testConnectWithNonJsonUrl() throws Exception {
158+
// Setup for connect with URL not ending in .json
159+
String agentCardJson = "{\"name\":\"Test Agent\",\"description\":\"Test Description\",\"agent_type\":\"a2a\"}";
160+
161+
// Mock URL and connection
162+
URL mockUrl = mock(URL.class);
163+
try (MockedStatic<URL> mockedUrl = mockStatic(URL.class)) {
164+
mockedUrl.when(() -> new URL(anyString())).thenReturn(mockUrl);
165+
when(mockUrl.openConnection()).thenReturn(mockConnection);
166+
when(mockConnection.getInputStream()).thenReturn(new ByteArrayInputStream(agentCardJson.getBytes()));
167+
when(mockConnection.getResponseCode()).thenReturn(200);
168+
169+
// Execute connect with URL ending with /
170+
a2aAgent.connect("http://test-url/", null);
171+
172+
// Verify connect
173+
assertTrue(a2aAgent.isConnected());
174+
175+
// Execute connect with URL not ending with /
176+
a2aAgent.connect("http://test-url", null);
177+
178+
// Verify connect
179+
assertTrue(a2aAgent.isConnected());
180+
}
181+
}
182+
183+
@Test
184+
void testConnectFailureInvalidUrl() {
185+
// Test with invalid URL (not containing .well-known)
186+
assertThrows(IllegalArgumentException.class, () ->
187+
a2aAgent.connect("http://test-url/invalid.json", null)
188+
);
189+
}
190+
191+
@Test
192+
void testConnectFailureHttp() throws Exception {
193+
// Setup for HTTP failure
194+
URL mockUrl = mock(URL.class);
195+
try (MockedStatic<URL> mockedUrl = mockStatic(URL.class)) {
196+
mockedUrl.when(() -> new URL(anyString())).thenReturn(mockUrl);
197+
when(mockUrl.openConnection()).thenReturn(mockConnection);
198+
when(mockConnection.getResponseCode()).thenReturn(404);
199+
200+
// Execute and verify
201+
assertThrows(RuntimeException.class, () ->
202+
a2aAgent.connect("http://test-url/.well-known/agent.json", null)
203+
);
204+
}
205+
}
206+
207+
@Test
208+
void testConnectFailureIO() throws Exception {
209+
// Setup for IO Exception
210+
URL mockUrl = mock(URL.class);
211+
try (MockedStatic<URL> mockedUrl = mockStatic(URL.class)) {
212+
mockedUrl.when(() -> new URL(anyString())).thenReturn(mockUrl);
213+
when(mockUrl.openConnection()).thenThrow(new IOException("Test IO Exception"));
214+
215+
// Execute and verify
216+
assertThrows(RuntimeException.class, () ->
217+
a2aAgent.connect("http://test-url/.well-known/agent.json", null)
218+
);
219+
}
220+
}
221+
222+
@Test
223+
void testGetterMethods() throws Exception {
224+
// Setup
225+
String agentCardJson = "{\"name\":\"Test Agent\",\"description\":\"Test Description\",\"agent_type\":\"a2a\"}";
226+
227+
// Mock URL and connection
228+
URL mockUrl = mock(URL.class);
229+
try (MockedStatic<URL> mockedUrl = mockStatic(URL.class)) {
230+
mockedUrl.when(() -> new URL(anyString())).thenReturn(mockUrl);
231+
when(mockUrl.openConnection()).thenReturn(mockConnection);
232+
when(mockConnection.getInputStream()).thenReturn(new ByteArrayInputStream(agentCardJson.getBytes()));
233+
when(mockConnection.getResponseCode()).thenReturn(200);
234+
235+
// Connect
236+
a2aAgent.connect("http://test-url/.well-known/agent.json", null);
237+
238+
// Test getters
239+
assertEquals(mockUrl, a2aAgent.getServerUrl());
240+
assertNotNull(a2aAgent.getMapper());
241+
AgentInfo info = a2aAgent.getInfo();
242+
assertNotNull(info);
243+
AgentCard agentCard = (AgentCard) info;
244+
assertEquals("Test Agent", agentCard.getName());
245+
}
246+
}
247+
}

0 commit comments

Comments
 (0)