testutil

package
v1.28.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 18, 2026 License: MIT Imports: 20 Imported by: 0

README

Test Utilities

This package provides shared testing utilities for the MCP server tests in both twprojects and twdesk packages.

Overview

The testutil package centralizes common test infrastructure to avoid code duplication and provide consistent testing patterns across all MCP tool implementations.

Usage

For Teamwork Projects Tests
import "github.com/teamwork/mcp/internal/testutil"

func TestSomething(t *testing.T) {
    mcpServer := testutil.ProjectsMCPServerMock(t, http.StatusOK, []byte(`{"id": 123}`))

    // Use testutil.ExecuteToolRequest for simple cases
    testutil.ExecuteToolRequest(t, mcpServer, "twprojects-get_comment", map[string]any{
        "id": float64(123),
    })
}
For Teamwork Desk Tests
import "github.com/teamwork/mcp/internal/testutil"

func TestSomething(t *testing.T) {
    mcpServer, cleanup := testutil.DeskMCPServerMock(t, http.StatusOK, []byte(`{"ticket_priority": {"id": 123}}`))
    defer cleanup()

    // Use testutil.ExecuteToolRequest for simple cases
    testutil.ExecuteToolRequest(t, mcpServer, "twdesk-get_priority", map[string]any{
        "id": 123,
    })
}

Components

  • ProjectsMCPServerMock: Creates a mock MCP server for testing twprojects tools
  • DeskMCPServerMock: Creates a mock MCP server for testing twdesk tools (with cleanup function)
  • CheckMessage: Validates that a tool execution was successful
  • ExecuteToolRequest: Helper to execute a tool request and validate the response
  • ToolRequest: Type alias for tool request structures

Migration Guide

To migrate existing tests to use the shared infrastructure:

  1. Replace your local mcpServerMock function calls with testutil.ProjectsMCPServerMock or testutil.DeskMCPServerMock
  2. Replace your local checkMessage function with testutil.CheckMessage
  3. Replace your local toolRequest type with testutil.ToolRequest
  4. Update imports to include "github.com/teamwork/mcp/internal/testutil"

This approach ensures consistency across all test suites and makes it easier to add new tool test suites in the future.

Documentation

Overview

Package testutil provides shared testing utilities for MCP server tests.

Package testutil provides schema validation helpers for testing MCP tools

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ChatMCPServerMock added in v1.21.4

func ChatMCPServerMock(t *testing.T, status int, response []byte) *mcp.Server

ChatMCPServerMock creates a mock MCP server for twchat testing. The twchat tools ride the shared twapi.Engine, so it reuses ProjectsEngineMock to return the canned HTTP response.

func CheckMessage

func CheckMessage(t *testing.T, result mcp.Result)

CheckMessage validates that a message represents a successful tool execution

func DeskClientMock

func DeskClientMock(status int, response []byte) (*deskclient.Client, *httptest.Server)

DeskClientMock creates a mock desk client with a test server

func DeskMCPServerMock

func DeskMCPServerMock(t *testing.T, status int, response []byte) (*mcp.Server, func())

DeskMCPServerMock creates a mock MCP server for twdesk testing It injects the test server URL into the request context so handlers use the correct endpoint

func DeskMCPServerMockWithRequest added in v1.28.0

func DeskMCPServerMockWithRequest(
	t *testing.T,
	status int,
	response []byte,
) (*mcp.Server, func() (string, url.URL), func())

DeskMCPServerMockWithRequest is like DeskMCPServerMockWithRequestURL but also reports the HTTP method of the most recent request.

The method is what separates some tools from each other: the ticket task link and unlink tools address the same path and differ only in POST versus DELETE, so a test that checks the URL alone passes when the two are swapped.

func DeskMCPServerMockWithRequestURL added in v1.27.1

func DeskMCPServerMockWithRequestURL(
	t *testing.T,
	status int,
	response []byte,
) (*mcp.Server, func() url.URL, func())

DeskMCPServerMockWithRequestURL is like DeskMCPServerMock but also captures the URL of the most recent HTTP request a tool sent, so tests can assert on the query string the tool actually builds.

Asserting the response alone cannot catch a filter or pagination parameter that is never sent: the mock replies with the same canned body regardless, so a dropped parameter looks identical to a working one.

The URL is returned through an accessor rather than a pointer because the capture happens on the httptest server's goroutine.

func ExecuteToolRequest

func ExecuteToolRequest(
	t *testing.T,
	mcpServer *mcp.Server,
	toolName string,
	args map[string]any,
	optFuncs ...ExecuteToolRequestOption,
)

ExecuteToolRequest executes a tool request and validates the response

func GetInvalidTestData added in v1.5.8

func GetInvalidTestData() map[string]map[string]map[string]any

GetInvalidTestData returns invalid test data for all tools

func GetValidTestData added in v1.5.8

func GetValidTestData() map[string]map[string]map[string]any

GetValidTestData returns valid test data for all tools. All required fields (including nullable optional ones) must be provided — pass nil to satisfy a required nullable field without setting a value.

func ProjectsEngineMock

func ProjectsEngineMock(status int, response []byte) *twapi.Engine

ProjectsEngineMock creates a mock twapi.Engine with the given HTTP response

func ProjectsMCPServerMock

func ProjectsMCPServerMock(t *testing.T, status int, response []byte) *mcp.Server

ProjectsMCPServerMock creates a mock MCP server for twprojects testing

func ProjectsMCPServerMockWithRequestBody added in v1.23.0

func ProjectsMCPServerMockWithRequestBody(t *testing.T, status int, response []byte) (*mcp.Server, *[]byte)

ProjectsMCPServerMockWithRequestBody is like ProjectsMCPServerMock but also captures the body of the most recent HTTP request the engine sent, so tests can assert on the serialized request payload. The returned pointer is populated after a tool invokes the engine.

func ProjectsMCPServerMockWithRequestURL added in v1.26.5

func ProjectsMCPServerMockWithRequestURL(t *testing.T, status int, response []byte) (*mcp.Server, *url.URL)

ProjectsMCPServerMockWithRequestURL is like ProjectsMCPServerMock but also captures the URL of the most recent HTTP request the engine sent, so tests can assert on the query string a tool actually builds. The returned pointer is populated after a tool invokes the engine.

Asserting the response alone cannot catch a filter or pagination parameter that is never sent: the mock replies with the same canned body regardless, so a dropped parameter looks identical to a working one.

func ProjectsMCPServerMockWithRequestURLs added in v1.28.3

func ProjectsMCPServerMockWithRequestURLs(t *testing.T, status int, response []byte) (*mcp.Server, *[]url.URL)

ProjectsMCPServerMockWithRequestURLs is like ProjectsMCPServerMockWithRequestURL but captures every request the engine sends rather than only the last one.

Use it when the tool under test makes more than one call, because the last URL is then the follow-up rather than the one being asserted on: list_custom_item_records resolves the custom item's field schema after listing, so its list query string is already gone by the time the tool returns, and a test reading lastURL reports the ordering missing from a request that never carried it.

func ProjectsMCPServerRecordingMock added in v1.27.4

func ProjectsMCPServerRecordingMock(
	t *testing.T,
	routes []ProjectsMockRoute,
	fallbackStatus int,
	fallbackBody []byte,
) (*mcp.Server, *[]ProjectsRecordedRequest)

ProjectsMCPServerRecordingMock is like ProjectsMCPServerRoutedMock but records every request in order rather than only the last body. Tools that fan one call out into many writes need this: the order of those writes is part of the contract (move_tasks must patch a parent before its children), and a single captured body cannot show it.

func ProjectsMCPServerRoutedMock added in v1.21.0

func ProjectsMCPServerRoutedMock(
	t *testing.T,
	routes []ProjectsMockRoute,
	fallbackStatus int,
	fallbackBody []byte,
) *mcp.Server

ProjectsMCPServerRoutedMock creates a mock MCP server for twprojects testing whose engine returns different responses based on a substring match against the request URL. Use this when a single tool dispatches calls to multiple endpoints that need distinct status codes (e.g. record create, which lists fields with 200 before posting the record with 201). Requests that don't match any route fall back to fallbackStatus/fallbackBody.

func ProjectsMCPServerRoutedMockWithRequestBody added in v1.25.3

func ProjectsMCPServerRoutedMockWithRequestBody(
	t *testing.T,
	routes []ProjectsMockRoute,
	fallbackStatus int,
	fallbackBody []byte,
) (*mcp.Server, *[]byte)

ProjectsMCPServerRoutedMockWithRequestBody is like ProjectsMCPServerRoutedMock but also captures the body of the most recent HTTP request that carried one, so tests can assert on the serialized payload of the final write while still serving distinct responses per endpoint (e.g. a field-type GET at 200 followed by a value POST at 201).

func ProjectsMCPServerSequencedMock added in v1.24.0

func ProjectsMCPServerSequencedMock(t *testing.T, status int, responses ...[]byte) *mcp.Server

ProjectsMCPServerSequencedMock creates a mock MCP server for twprojects testing whose engine returns the given response bodies in order, one per HTTP request the engine makes. Once the sequence is exhausted the final body is repeated. This lets tests drive a tool's internal pagination loop with a distinct body per page, or exercise a never-ending "hasMore" by supplying a single always-more body. All responses share the same status code.

func SpacesMCPServerMock added in v1.15.0

func SpacesMCPServerMock(t *testing.T, status int, response []byte) (*mcp.Server, func())

SpacesMCPServerMock creates a mock MCP server for twspaces testing. It injects the test server URL into the request context so handlers use the correct endpoint.

Types

type ExecuteToolRequestOption added in v1.6.2

type ExecuteToolRequestOption func(*ExecuteToolRequestOptions)

ExecuteToolRequestOption is a function that modifies ExecuteToolRequestOptions.

func ExecuteToolRequestWithCheckMessage added in v1.6.2

func ExecuteToolRequestWithCheckMessage(f func(t *testing.T, result mcp.Result)) ExecuteToolRequestOption

ExecuteToolRequestWithCheckMessage executes a tool request and validates the response with a custom check function. Any nil function will be ignored.

type ExecuteToolRequestOptions added in v1.6.2

type ExecuteToolRequestOptions struct {
	// contains filtered or unexported fields
}

ExecuteToolRequestOptions represents options for ExecuteToolRequest.

type ProjectsMockRoute added in v1.21.0

type ProjectsMockRoute struct {
	Match string
	// Method restricts the route to a single HTTP method. An empty value matches
	// any method, which is what path-only routing needs; set it when one path
	// serves several verbs, as /tasks/{id}.json does for get and update.
	Method string
	Status int
	Body   []byte
}

ProjectsMockRoute pairs a substring match against the request URL path with the status and body to return when it matches.

type ProjectsRecordedRequest added in v1.27.4

type ProjectsRecordedRequest struct {
	Method string
	// URL is the whole request URL, not only its path: a tool that reaches an
	// endpoint outside the API, as the pre-signed file upload does, is only
	// identifiable by its host, and a step that carries its parameters in the
	// query string has nothing in its body to assert on.
	URL  url.URL
	Body []byte
}

ProjectsRecordedRequest is one HTTP request captured by ProjectsMCPServerRecordingMock.

type ProjectsSessionMock

type ProjectsSessionMock struct{}

ProjectsSessionMock implements a mock session for twprojects testing

func (ProjectsSessionMock) Authenticate

Authenticate implements the Authenticate method for ProjectsSessionMock

func (ProjectsSessionMock) Server

func (s ProjectsSessionMock) Server() string

Server implements the Server method for ProjectsSessionMock

type SchemaValidationTestSuite added in v1.5.8

type SchemaValidationTestSuite struct {
	// contains filtered or unexported fields
}

SchemaValidationTestSuite provides a comprehensive test suite for validating MCP tool JSON schemas

func NewSchemaValidationTestSuite added in v1.5.8

func NewSchemaValidationTestSuite() *SchemaValidationTestSuite

NewSchemaValidationTestSuite creates a new test suite with all twdesk tools

func (*SchemaValidationTestSuite) GetTool added in v1.5.8

func (s *SchemaValidationTestSuite) GetTool(toolName string) (toolsets.ToolWrapper, bool)

GetTool returns a tool by name if it exists

func (*SchemaValidationTestSuite) RunAllSchemaValidationTests added in v1.5.8

func (s *SchemaValidationTestSuite) RunAllSchemaValidationTests(t *testing.T)

RunAllSchemaValidationTests runs comprehensive schema validation tests for all tools

func (*SchemaValidationTestSuite) RunToolSchemaValidation added in v1.5.8

func (s *SchemaValidationTestSuite) RunToolSchemaValidation(t *testing.T, toolName string, tool toolsets.ToolWrapper)

RunToolSchemaValidation runs schema validation tests for a single tool (exported version)

type ToolRequest

type ToolRequest struct {
	mcp.CallToolRequest

	JSONRPC string `json:"jsonrpc"`
	ID      int64  `json:"id"`
}

ToolRequest represents a tool request for testing

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL