Skip to content

Commit 2f5738a

Browse files
author
klapaudius
committed
Refactor and add tests for improved MCPServer and resource handling
Added PHPDoc comments to MCPServerTest for better documentation of test cases. Introduced comprehensive tests for McpDocumentationResource ensuring accurate URI handling, MIME type guessing, and resource management. Cleaned up unnecessary verbosity in KlpMcpServerExtensionTest comments for clarity.
1 parent 657e7a6 commit 2f5738a

File tree

3 files changed

+193
-9
lines changed

3 files changed

+193
-9
lines changed

tests/DependencyInjection/KlpMcpServerExtensionTest.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ protected function setUp(): void
2727

2828

2929
/**
30-
* Tests that all parameters are correctly set when loading a valid configuration.
31-
*
32-
* @return void
30+
* Tests that all parameters are correctly set when loading a valid configuration
3331
*/
3432
public function test_load_sets_all_parameters_correctly(): void
3533
{
@@ -85,9 +83,7 @@ public function test_load_sets_all_parameters_correctly(): void
8583
}
8684

8785
/**
88-
* Tests that an exception is thrown when an invalid configuration is provided.
89-
*
90-
* @return void
86+
* Tests that an exception is thrown when an invalid configuration is provided
9187
*/
9288
public function test_load_throws_exception_for_invalid_config(): void
9389
{

tests/Server/MCPServerTest.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#[Small]
2323
class MCPServerTest extends TestCase
2424
{
25+
/**
26+
* Tests that tool repository registration correctly registers the required handlers
27+
*/
2528
public function test_register_tool_repository(): void
2629
{
2730
// Arrange
@@ -51,6 +54,9 @@ public function test_register_tool_repository(): void
5154
// Assert: Expectations set on the mock protocol are automatically verified.
5255
}
5356

57+
/**
58+
* Tests that registerToolRepository method returns the server instance for method chaining
59+
*/
5460
public function test_register_tool_repository_returns_instance(): void
5561
{
5662
// Arrange
@@ -69,6 +75,9 @@ public function test_register_tool_repository_returns_instance(): void
6975
$this->assertSame($instance, $result);
7076
}
7177

78+
/**
79+
* Tests that request handler registration delegates to the protocol implementation
80+
*/
7281
public function test_register_request_handler(): void
7382
{
7483
// Arrange
@@ -88,6 +97,9 @@ public function test_register_request_handler(): void
8897
// Assert: Expectations set on the mock objects are automatically verified
8998
}
9099

100+
/**
101+
* Tests that the create method properly instantiates a server with basic configuration
102+
*/
91103
public function test_create(): void
92104
{
93105
// Arrange
@@ -104,6 +116,9 @@ public function test_create(): void
104116
$this->assertSame(['name' => $name, 'version' => $version], $this->getPrivateProperty($server, 'serverInfo'));
105117
}
106118

119+
/**
120+
* Tests that the create method properly instantiates a server with custom capabilities
121+
*/
107122
public function test_create_with_capabilities(): void
108123
{
109124
// Arrange
@@ -130,6 +145,9 @@ private function getPrivateProperty(object $object, string $property)
130145
return $prop->getValue($object);
131146
}
132147

148+
/**
149+
* Tests that connect method calls the protocol's connect method
150+
*/
133151
public function test_connect(): void
134152
{
135153
// Arrange
@@ -148,6 +166,9 @@ public function test_connect(): void
148166
// Assert: Expectations set on the mock objects are automatically verified.
149167
}
150168

169+
/**
170+
* Tests that disconnect method calls the protocol's disconnect method
171+
*/
151172
public function test_disconnect(): void
152173
{
153174
// Arrange
@@ -166,6 +187,9 @@ public function test_disconnect(): void
166187
// Assert: Expectations set on the mock objects are automatically verified.
167188
}
168189

190+
/**
191+
* Tests that notification handler registration delegates to the protocol implementation
192+
*/
169193
public function test_register_notification_handler(): void
170194
{
171195
// Arrange
@@ -186,6 +210,9 @@ public function test_register_notification_handler(): void
186210
// Assert: Expectations set on the mock objects are automatically verified.
187211
}
188212

213+
/**
214+
* Tests that request message is properly forwarded to the protocol implementation
215+
*/
189216
public function test_request_message(): void
190217
{
191218
// Arrange
@@ -209,7 +236,7 @@ public function test_request_message(): void
209236

210237
/**
211238
* Tests that the initialize method correctly sets the client capabilities,
212-
* assigns the protocol version, and marks the server as initialized.
239+
* assigns the protocol version, and marks the server as initialized
213240
*/
214241
public function test_initialize_sets_capabilities_and_marks_initialized(): void
215242
{
@@ -236,7 +263,7 @@ public function test_initialize_sets_capabilities_and_marks_initialized(): void
236263

237264
/**
238265
* Tests that the initialize method throws an exception if the server
239-
* has already been initialized.
266+
* has already been initialized
240267
*/
241268
public function test_initialize_throws_when_already_initialized(): void
242269
{
@@ -265,7 +292,7 @@ public function test_initialize_throws_when_already_initialized(): void
265292

266293
/**
267294
* Tests that the initialize method returns a correctly constructed
268-
* InitializeResource object with expected values.
295+
* InitializeResource object with expected values
269296
*/
270297
public function test_initialize_returns_correct_resource(): void
271298
{
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<?php
2+
3+
namespace KLP\KlpMcpServer\Tests\Services\ResourceService;
4+
5+
use KLP\KlpMcpServer\Services\ResourceService\Examples\McpDocumentationResource;
6+
use KLP\KlpMcpServer\Services\ResourceService\ResourceInterface;
7+
use PHPUnit\Framework\Attributes\Small;
8+
use PHPUnit\Framework\TestCase;
9+
use Symfony\Component\HttpKernel\KernelInterface;
10+
11+
#[Small]
12+
class McpDocumentationResourceTest extends TestCase
13+
{
14+
private KernelInterface $kernel;
15+
private McpDocumentationResource $resource;
16+
private string $baseDir;
17+
18+
protected function setUp(): void
19+
{
20+
$this->baseDir = '/tmp/mcp-docs';
21+
22+
// Create mock kernel
23+
$this->kernel = $this->createMock(KernelInterface::class);
24+
$this->kernel->method('getProjectDir')
25+
->willReturn('/tmp');
26+
27+
// Create the resource
28+
$this->resource = new McpDocumentationResource($this->kernel);
29+
30+
// Use reflection to set the baseDir property
31+
$reflectionClass = new \ReflectionClass(McpDocumentationResource::class);
32+
$property = $reflectionClass->getProperty('baseDir');
33+
$property->setAccessible(true);
34+
$property->setValue($this->resource, $this->baseDir);
35+
36+
// Create test directory and files
37+
if (!file_exists($this->baseDir)) {
38+
mkdir($this->baseDir, 0777, true);
39+
}
40+
41+
// Create test markdown files
42+
file_put_contents($this->baseDir . '/test1.md', "# Test Document 1\nThis is a test document.");
43+
file_put_contents($this->baseDir . '/test2.md', "# Test Document 2\nThis is another test document.");
44+
}
45+
46+
protected function tearDown(): void
47+
{
48+
// Clean up test files
49+
if (file_exists($this->baseDir . '/test1.md')) {
50+
unlink($this->baseDir . '/test1.md');
51+
}
52+
if (file_exists($this->baseDir . '/test2.md')) {
53+
unlink($this->baseDir . '/test2.md');
54+
}
55+
if (file_exists($this->baseDir)) {
56+
rmdir($this->baseDir);
57+
}
58+
}
59+
60+
/**
61+
* Tests that the URI template is correctly formatted for documentation files
62+
*/
63+
public function test_get_uri_template(): void
64+
{
65+
$this->assertSame("file:/docs/{filename}.md", $this->resource->getUriTemplate());
66+
}
67+
68+
/**
69+
* Tests that the resource name is correctly returned
70+
*/
71+
public function test_get_name(): void
72+
{
73+
$this->assertSame("documentation.md", $this->resource->getName());
74+
}
75+
76+
/**
77+
* Tests that the description contains expected content including references to test files
78+
*/
79+
public function test_get_description(): void
80+
{
81+
$description = $this->resource->getDescription();
82+
$this->assertStringContainsString("The MCP Documentation resources", $description);
83+
$this->assertStringContainsString("test1", $description);
84+
$this->assertStringContainsString("test2", $description);
85+
}
86+
87+
/**
88+
* Tests that the MIME type is correctly returned as plain text
89+
*/
90+
public function test_get_mime_type(): void
91+
{
92+
$this->assertSame("text/plain", $this->resource->getMimeType());
93+
}
94+
95+
/**
96+
* Tests that a resource can be correctly retrieved and contains expected properties
97+
*/
98+
public function test_get_resource(): void
99+
{
100+
$uri = "file:/docs/test1.md";
101+
$resource = $this->resource->getResource($uri);
102+
103+
$this->assertInstanceOf(ResourceInterface::class, $resource);
104+
$this->assertSame($uri, $resource->getUri());
105+
$this->assertSame("test1.md", $resource->getName());
106+
$this->assertSame("# Test Document 1", $resource->getDescription());
107+
$this->assertStringContainsString("text/", $resource->getMimeType());
108+
$this->assertSame("# Test Document 1\nThis is a test document.", $resource->getData());
109+
}
110+
111+
/**
112+
* Tests that null is returned when attempting to retrieve a resource with an invalid URI
113+
*/
114+
public function test_get_resource_with_invalid_uri(): void
115+
{
116+
$uri = "file:/docs/nonexistent.md";
117+
$resource = $this->resource->getResource($uri);
118+
119+
$this->assertNull($resource);
120+
}
121+
122+
/**
123+
* Tests that the resource existence check correctly identifies valid and invalid resources
124+
*/
125+
public function test_resource_exists(): void
126+
{
127+
$this->assertTrue($this->resource->resourceExists("file:/docs/test1.md"));
128+
$this->assertTrue($this->resource->resourceExists("file:/docs/test2.md"));
129+
$this->assertFalse($this->resource->resourceExists("file:/docs/nonexistent.md"));
130+
$this->assertFalse($this->resource->resourceExists("invalid-uri"));
131+
}
132+
133+
/**
134+
* Tests that filenames are correctly extracted from URIs
135+
*/
136+
public function test_get_filename_from_uri(): void
137+
{
138+
// Use reflection to access private method
139+
$reflectionClass = new \ReflectionClass(McpDocumentationResource::class);
140+
$method = $reflectionClass->getMethod('getFilenameFromUri');
141+
$method->setAccessible(true);
142+
143+
$this->assertSame("test1", $method->invoke($this->resource, "file:/docs/test1.md"));
144+
$this->assertSame("test2", $method->invoke($this->resource, "file:/docs/test2.md"));
145+
$this->assertNull($method->invoke($this->resource, "invalid-uri"));
146+
}
147+
148+
/**
149+
* Tests that the MIME type is correctly guessed from a file
150+
*/
151+
public function test_guess_mime_type(): void
152+
{
153+
// Use reflection to access protected method
154+
$reflectionClass = new \ReflectionClass(McpDocumentationResource::class);
155+
$method = $reflectionClass->getMethod('guessMimeType');
156+
$method->setAccessible(true);
157+
158+
$mimeType = $method->invoke($this->resource, $this->baseDir . '/test1.md');
159+
$this->assertStringContainsString("text/", $mimeType);
160+
}
161+
}

0 commit comments

Comments
 (0)