Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add mocked client interface for testing #163

@echarrod

Description

@echarrod

Feature Request: Add Mock Client Interface

Problem Statement

Currently, when building applications that depend on the luno-go SDK, developers need to create their own interface wrapper around the luno.Client in order to mock it for testing. This adds unnecessary boilerplate and complexity to every project that wants to write comprehensive unit tests.

For example, in luno-mcp we had to create this interface:

// LunoClient defines the interface for Luno API operations
// This interface allows us to mock the Luno client for testing
type LunoClient interface {
    GetBalances(ctx context.Context, req *luno.GetBalancesRequest) (*luno.GetBalancesResponse, error)
    GetTicker(ctx context.Context, req *luno.GetTickerRequest) (*luno.GetTickerResponse, error)
    GetOrderBook(ctx context.Context, req *luno.GetOrderBookRequest) (*luno.GetOrderBookResponse, error)
    PostLimitOrder(ctx context.Context, req *luno.PostLimitOrderRequest) (*luno.PostLimitOrderResponse, error)
    StopOrder(ctx context.Context, req *luno.StopOrderRequest) (*luno.StopOrderResponse, error)
    ListOrders(ctx context.Context, req *luno.ListOrdersRequest) (*luno.ListOrdersResponse, error)
    ListTransactions(ctx context.Context, req *luno.ListTransactionsRequest) (*luno.ListTransactionsResponse, error)
    ListTrades(ctx context.Context, req *luno.ListTradesRequest) (*luno.ListTradesResponse, error)
}

And then generate mocks using mockery or similar tools.

Proposed Solution

The luno-go SDK could provide:

  1. A public interface that defines all the client methods
  2. A generated mock implementation that can be used in tests
  3. Ensure the main Client struct implements this interface

This would follow the pattern used by many other Go SDKs and would significantly improve the developer experience.

Benefits

  • Reduced boilerplate: Developers don't need to create their own interface wrapper
  • Consistency: Everyone uses the same interface definition
  • Maintainability: Interface updates are handled by the SDK maintainers
  • Better testing: Easy mocking enables comprehensive unit testing
  • Standard Go patterns: Follows established Go testing best practices

Example Implementation (taken what we've done on https://github.com/luno/luno-mcp):

// ClientInterface defines all Luno API operations
type ClientInterface interface {
    GetBalances(ctx context.Context, req *GetBalancesRequest) (*GetBalancesResponse, error)
    GetTicker(ctx context.Context, req *GetTickerRequest) (*GetTickerResponse, error)
    // ... all other client methods
}

// Ensure Client implements the interface
var _ ClientInterface = (*Client)(nil)

// MockClient can be generated using go:generate mockery
//go:generate mockery --name=ClientInterface --output=./mocks

Use Cases

  • Unit testing: Mock API responses for testing business logic
  • Integration testing: Verify API call parameters without making real requests
  • Development environments: Use fake implementations during development
  • CI/CD: Fast, reliable tests that don't depend on external APIs

Alternative Approaches Considered

  1. Manual interface creation (current approach): Requires every project to duplicate this work
  2. Embedding approach: Would require changing the existing Client struct significantly
  3. Factory pattern: More complex than needed for this use case

This would be a breaking change. It could be a minor version bump (as we're still pre v1.0.0), but it could also be a good opporunity to bump it to v1.0.0

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions