Skip to content

Commit 9565b67

Browse files
author
klapaudius
committed
Add new test cases and fix validation/schema logic
Added test cases for message handling with invalid params, missing methods, and exception scenarios. Updated ToolParamsValidatorTest to fix argument type checks in schemas. Also updated composer dependencies to include symfony/routing for expanded functionality.
1 parent bc067f6 commit 9565b67

File tree

3 files changed

+113
-6
lines changed

3 files changed

+113
-6
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"psr/log": "^3.0",
1212
"symfony/console": "~7.0",
1313
"symfony/dependency-injection": "~7.0",
14-
"symfony/http-foundation": "~7.0"
14+
"symfony/http-foundation": "~7.0",
15+
"symfony/routing": "^7.2"
1516
},
1617
"require-dev": {
1718
"phpunit/phpunit": "~11.0",

tests/Protocol/MCPProtocolTest.php

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace KLP\KlpMcpServer\Tests\Protocol;
44

5+
use KLP\KlpMcpServer\Exceptions\ToolParamsValidatorException;
6+
use KLP\KlpMcpServer\Protocol\Handlers\NotificationHandler;
57
use KLP\KlpMcpServer\Protocol\MCPProtocol;
68
use KLP\KlpMcpServer\Transports\TransportInterface;
79
use PHPUnit\Framework\Attributes\Small;
@@ -202,7 +204,7 @@ public function test_handle_message_handles_valid_notification(): void
202204
$clientId = 'client_1';
203205
$validNotificationMessage = ['jsonrpc' => '2.0', 'method' => 'notify.method', 'params' => ['param1' => 'value1']];
204206

205-
$mockHandler = $this->createMock(\KLP\KlpMcpServer\Protocol\Handlers\NotificationHandler::class);
207+
$mockHandler = $this->createMock(NotificationHandler::class);
206208
$mockHandler->method('isHandle')->with('notify.method')->willReturn(true);
207209
$mockHandler->expects($this->once())->method('execute')->with(['param1' => 'value1']);
208210
$this->mcpProtocol->registerNotificationHandler($mockHandler);
@@ -262,4 +264,108 @@ public function test_handle_message_handles_unknown_notification(): void
262264

263265
$this->mcpProtocol->handleMessage($clientId, $unknownNotificationMessage);
264266
}
267+
268+
public function test_handle_message_handles_no_method(): void
269+
{
270+
$clientId = 'client_1';
271+
$noMethodMessage = ['jsonrpc' => '2.0', 'id' => 1];
272+
273+
$this->mockTransport
274+
->expects($this->once())
275+
->method('pushMessage')
276+
->with($this->callback(function (...$args) use ($clientId) {
277+
$data = $args[1];
278+
$this->assertEquals($clientId, $args[0]);
279+
$this->assertEquals('2.0', $data['jsonrpc']);
280+
$this->assertEquals(1, $data['id']);
281+
$this->assertEquals(-32600, $data['error']['code']);
282+
$this->assertEquals('Invalid Request: Message format not recognized', $data['error']['message']);
283+
return true;
284+
}));
285+
286+
$this->mcpProtocol->handleMessage($clientId, $noMethodMessage);
287+
}
288+
289+
public function test_handle_message_handles_invalid_params(): void
290+
{
291+
$clientId = 'client_1';
292+
$invalidParamsMessage = ['jsonrpc' => '2.0', 'id' => 1, 'method' => 'test.method', 'params' => ['param1' => 'invalid']];
293+
294+
$mockHandler = $this->createMock(\KLP\KlpMcpServer\Protocol\Handlers\RequestHandler::class);
295+
$mockHandler->method('isHandle')->with('test.method')->willReturn(true);
296+
$mockHandler->method('execute')->with('test.method', ['param1' => 'invalid'])
297+
->willThrowException(new ToolParamsValidatorException('An error occurred.', ['Invalid params param1']));
298+
299+
$this->mockTransport
300+
->expects($this->once())
301+
->method('pushMessage')
302+
->with($this->callback(function (...$args) use ($clientId) {
303+
$data = $args[1];
304+
$this->assertEquals($clientId, $args[0]);
305+
$this->assertEquals('2.0', $data['jsonrpc']);
306+
$this->assertEquals(1, $data['id']);
307+
$this->assertEquals(-32602, $data['error']['code']);
308+
309+
$this->assertEquals('An error occurred. Invalid params param1', $data['error']['message']);
310+
return true;
311+
}));
312+
313+
$this->mcpProtocol->registerRequestHandler($mockHandler);
314+
$this->mcpProtocol->handleMessage($clientId, $invalidParamsMessage);
315+
}
316+
317+
public function test_handle_message_handles_handler_throw_exception(): void
318+
{
319+
// Arrange
320+
$clientId = 'client_1';
321+
$invalidParamsMessage = ['jsonrpc' => '2.0', 'id' => 1, 'method' => 'test.method', 'params' => ['param1' => 'invalid']];
322+
$mockHandler = $this->createMock(\KLP\KlpMcpServer\Protocol\Handlers\RequestHandler::class);
323+
$mockHandler->method('isHandle')->with('test.method')->willReturn(true);
324+
$mockHandler->method('execute')->with('test.method', ['param1' => 'invalid'])
325+
->willThrowException(new \Exception('An error occurred.'));
326+
327+
$this->mockTransport
328+
->expects($this->once())
329+
->method('pushMessage')
330+
->with($this->callback(function (...$args) use ($clientId) {
331+
$data = $args[1];
332+
$this->assertEquals($clientId, $args[0]);
333+
$this->assertEquals('2.0', $data['jsonrpc']);
334+
$this->assertEquals(1, $data['id']);
335+
$this->assertEquals(-32603, $data['error']['code']);
336+
$this->assertEquals('An error occurred.', $data['error']['message']);
337+
return true;
338+
}));
339+
$this->mcpProtocol->registerRequestHandler($mockHandler);
340+
341+
// Act
342+
$this->mcpProtocol->handleMessage($clientId, $invalidParamsMessage);
343+
}
344+
345+
public function test_handle_message_handles_notification_handler_throw_exception(): void
346+
{
347+
$clientId = 'client_1';
348+
$validNotificationMessage = ['jsonrpc' => '2.0', 'method' => 'notify.method', 'params' => ['param1' => 'value1']];
349+
350+
$mockHandler = $this->createMock(NotificationHandler::class);
351+
$mockHandler->method('isHandle')->with('notify.method')->willReturn(true);
352+
$mockHandler->expects($this->once())->method('execute')
353+
->with(['param1' => 'value1'])
354+
->willThrowException(new \Exception('An error occurred.'));;
355+
$this->mcpProtocol->registerNotificationHandler($mockHandler);
356+
357+
$this->mockTransport
358+
->expects($this->once())
359+
->method('pushMessage')
360+
->with($this->callback(function (...$args) use ($clientId) {
361+
$data = $args[1];
362+
$this->assertEquals($clientId, $args[0]);
363+
$this->assertEquals('2.0', $data['jsonrpc']);
364+
$this->assertEquals(-32603, $data['error']['code']);
365+
$this->assertEquals('An error occurred.', $data['error']['message']);
366+
return true;
367+
}));
368+
369+
$this->mcpProtocol->handleMessage($clientId, $validNotificationMessage);
370+
}
265371
}

tests/Services/ToolService/ToolParamsValidatorTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,13 @@ public function test_validate_with_invalid_argument_not_in_schema(): void
7575
{
7676
$toolSchema = [
7777
'arguments' => [
78-
'arg1' => ['type' => 'string'],
78+
'arg1' => ['type' => 'array'],
7979
],
8080
'required' => ['arg1'],
8181
];
8282

8383
$arguments = [
84-
'arg1' => 'validString',
84+
'arg1' => ['validArray'],
8585
'arg2' => 'extra',
8686
];
8787

@@ -101,7 +101,7 @@ public function test_validate_with_invalid_argument_type(): void
101101
$toolSchema = [
102102
'arguments' => [
103103
'arg1' => ['type' => 'string'],
104-
'arg2' => ['type' => 'integer'],
104+
'arg2' => ['type' => 'boolean'],
105105
],
106106
'required' => ['arg1', 'arg2'],
107107
];
@@ -117,7 +117,7 @@ public function test_validate_with_invalid_argument_type(): void
117117
try {
118118
ToolParamsValidator::validate($toolSchema, $arguments);
119119
} catch (ToolParamsValidatorException $exception) {
120-
$this->assertContains('Invalid argument type for: arg2. Expected: integer, got: string', $exception->getErrors());
120+
$this->assertContains('Invalid argument type for: arg2. Expected: boolean, got: string', $exception->getErrors());
121121
throw $exception;
122122
}
123123
}

0 commit comments

Comments
 (0)