Documentation ¶
Overview ¶
Package thrifttest contains objects and utility methods to aid with testing code using Thrift clients and servers.
Index ¶
- Constants
- func CopyTStruct(ctx context.Context, dst, src thrift.TStruct) error
- func GetMockTProcessorName(ctx context.Context) (string, bool)
- func SetMockTProcessorName(ctx context.Context, name string) context.Context
- type MockCall
- type MockClient
- func (c *MockClient) AddMockCall(method string, mock MockCall)
- func (c *MockClient) AddNopMockCalls(methods ...string)
- func (c *MockClient) Call(ctx context.Context, method string, args, result thrift.TStruct) (thrift.ResponseMeta, error)
- func (MockClient) Close() error
- func (MockClient) IsOpen() bool
- type MockClientPool
- type MockTProcessor
- type RecordedCall
- type RecordedClient
- type Server
- type ServerConfig
Examples ¶
Constants ¶
const ( // DefaultClientMaxConnections is used when ServerConfig.ClientConfig.MaxConnections // is not set. DefaultClientMaxConnections = 10 // DefaultClientConnectTimeout is used when ServerConfig.ClientConfig.ConnectTimeout // is not set. // // We use a relatively large number as the default timeout because we often // run tests from virtual environments with very limited resources. DefaultClientConnectTimeout = 500 * time.Millisecond // DefaultClientSocketTimeout is used when ServerConfig.ClientConfig.SocketTimeout // is not set. // // We use a relatively large number as the default timeout because we often // run tests from virtual environments with very limited resources. DefaultClientSocketTimeout = 500 * time.Millisecond // DefaultServiceSlug is used when ServerConfig.ClientConfig.ServiceSlug // is not set. DefaultServiceSlug = "testing" // InitialClientConnections is the value that is always used for // ServerConfig.ClientConfig.InitialConnections. // // We default to 0 becaues the service is not started in NewBaseplateServer so // we do not want to try to connect to it when initializing the ClientPool. InitialClientConnections = 0 // ReportClientPoolStats is the value that is always used for // ServerConfig.ClientConfig.ReportPoolStats. // // Deprecated: deprecated with the server config field. ReportClientPoolStats = false )
Variables ¶
This section is empty.
Functions ¶
func CopyTStruct ¶
CopyTStruct is a helper function that can be used to implement MockCall.
In thrift.TClient and MockCall interfaces, the result is passed in as an arg to the function, so you can't directly assign a result to it. Instead, you'll need to use this helper function to copy a constructed result to the arg.
Example:
myMockClient.AddMockCall( "myEndpoint", func(ctx context.Context, args, result thrift.TStruct) error { return thrifttest.CopyTStruct( ctx, result, &myservice.MyServiceMyEndpointResult{ Success: &myservice.MyEndpointResponse{ // Set the response fields. }, }, ) }, )
func GetMockTProcessorName ¶
GetMockTProcessorName gets the "name" of the TProcessorFunction to call on a MockTProcessor when calling Process.
func SetMockTProcessorName ¶
SetMockTProcessorName sets the "name" of the TProcessorFunction to call on a MockTProcessor when calling Process.
In a normal TProcessor, the request name is read from the request itself which happens in TProcessor.Process, so it is not passed into the call to Process itself, to get around this, MockTProcessor calls GetMockTProcessorName to get the name to use from the context object.
Types ¶
type MockClient ¶
type MockClient struct { FailUnregisteredMethods bool // contains filtered or unexported fields }
MockClient implements thrift.TClient and Client, and can be used to mock out thrift calls in testing by using it as the base client rather than a real client.
If a MockCall is registered to a method, then Call will return the result of that MockCall when that method is Call-ed. If no MockCall is registered to a method, Call will simply return nil when FailUnregisteredMethods is false, or an error when FailUnregisteredMethods is true.
MockClient is provided to help with unit testing and should not be used in production code.
func (*MockClient) AddMockCall ¶
func (c *MockClient) AddMockCall(method string, mock MockCall)
AddMockCall registers the given MockCall to the given method.
If a mock is already registered to that method, it will be replaced with the new mock.
AddMockCall is not thread-safe.
func (*MockClient) AddNopMockCalls ¶
func (c *MockClient) AddNopMockCalls(methods ...string)
AddNopMockCalls registers the nop MockCall to the given methods.
A nop MockCall is a MockCall implementation that does nothing and returns nil error.
func (*MockClient) Call ¶
func (c *MockClient) Call(ctx context.Context, method string, args, result thrift.TStruct) (thrift.ResponseMeta, error)
Call implements the thrift.TClient interface.
It will return the result of the MockCall registered to method if one exists. If the method is not registered, it returns an error when FailUnregisteredMethods is true, nil otherwise.
func (MockClient) Close ¶
func (MockClient) Close() error
Close implements Client and is a nop that always returns nil.
func (MockClient) IsOpen ¶
func (MockClient) IsOpen() bool
IsOpen implements Client and is a nop that always returns true.
type MockClientPool ¶
MockClientPool is a ClientPool implementation can be used in test code.
func (MockClientPool) Call ¶
func (m MockClientPool) Call(ctx context.Context, method string, args, result thrift.TStruct) (thrift.ResponseMeta, error)
Call implements TClient.
If Exhausted is set to true, it returns clientpool.ErrExhausted as the error.
If Exhausted is set to false, it creates a new client using the CreateClient field if it's set or uses default MockClient otherwise and uses that to implement Call.
func (MockClientPool) Close ¶
func (MockClientPool) Close() error
Close is nop and always returns nil error.
func (MockClientPool) IsExhausted ¶
func (m MockClientPool) IsExhausted() bool
IsExhausted returns Exhausted field.
func (MockClientPool) TClient ¶ added in v0.9.0
func (m MockClientPool) TClient() thrift.TClient
TClient implements thriftbp.ClientPool.
type MockTProcessor ¶
type MockTProcessor struct {
// contains filtered or unexported fields
}
MockTProcessor can be used to create a mock object that fufills the BaseplateProcessor interface in testing.
func NewMockTProcessor ¶
func NewMockTProcessor(tb testing.TB, processorMap map[string]thrift.TProcessorFunction) *MockTProcessor
NewMockTProcessor returns a pointer to a new MockTProcessor object with the internal processor map initialized to the one passed in.
If the passed in map is nil, an empty map will be initialized and passed in to the new object so it is safe to add to.
func (*MockTProcessor) AddToProcessorMap ¶
func (p *MockTProcessor) AddToProcessorMap(name string, processorFunc thrift.TProcessorFunction)
AddToProcessorMap adds the given TProcessorFunction to the internal processor map with the given name as the key.
func (*MockTProcessor) Process ¶
func (p *MockTProcessor) Process(ctx context.Context, in, out thrift.TProtocol) (bool, thrift.TException)
Process calls the TProcessorFunction assigned to the "name" set on the context object by SetMockTProcessorName.
If no name is set on the context or there is no TProcessorFunction mapped to that name, the call will fail the test.
func (*MockTProcessor) ProcessorMap ¶
func (p *MockTProcessor) ProcessorMap() map[string]thrift.TProcessorFunction
ProcessorMap returns the internal processor map.
type RecordedCall ¶
type RecordedCall struct { Ctx context.Context Method string // contains filtered or unexported fields }
RecordedCall records the inputs passed to RecordedClient.RecordedCall.
type RecordedClient ¶
type RecordedClient struct {
// contains filtered or unexported fields
}
RecordedClient implements the thrift.TClient interface and records the inputs to each Call.
RecordedClient is provided to help with unit testing and should not be used in production code.
RecordedClient is not thread-safe.
func NewRecordedClient ¶
func NewRecordedClient(c thrift.TClient) *RecordedClient
NewRecordedClient returns a pointer to a new RecordedClient that wraps the provided client.
func (*RecordedClient) Call ¶
func (c *RecordedClient) Call(ctx context.Context, method string, args, result thrift.TStruct) (thrift.ResponseMeta, error)
Call fufills the thrift.TClient interface. It will record the inputs to Call and either return the result of the inner client.Call or nil if the inner client is nil.
func (RecordedClient) Calls ¶
func (c RecordedClient) Calls() []RecordedCall
Calls returns a copy of all of recorded Calls.
Calls is not thread-safe and may panic if used across threads if the number of calls changes between the copy buffer being intialized and copied.
type Server ¶ added in v0.2.1
type Server struct { baseplate.Server // ClientPool provides a thriftbp.ClientPool that connects to this Server and // can be used for making Thrift client objects to interact with this Server. ClientPool thriftbp.ClientPool }
Server is a test server returned by NewBaseplateServer. It contains both the baseplate.Server and a ClientPool to use to interact with the server.
Server implements baseplate.Server.
func NewBaseplateServer ¶ added in v0.2.1
func NewBaseplateServer(cfg ServerConfig) (*Server, error)
NewBaseplateServer returns a new, Baseplate thrift server listening on the local loopback interface and a Baseplate ClientPool for use with that server.
This is inspired by httptest.NewServer from the go standard library and can be used to test a thrift service.
Example ¶
This example demonstrates how to write an unit test with mocked thrift server using NewBaseplateServer.
package main import ( "context" "testing" baseplatethrift "github.com/reddit/baseplate.go/internal/gen-go/reddit/baseplate" "github.com/reddit/baseplate.go/secrets" "github.com/reddit/baseplate.go/thriftbp/thrifttest" ) type mockedBaseplateService struct { Fail bool Err error } func (srv mockedBaseplateService) IsHealthy(ctx context.Context, req *baseplatethrift.IsHealthyRequest) (r bool, err error) { return !srv.Fail, srv.Err } // In real test this function needs to be named TestService instead, // but doing that will break this example. func ServiceTest(t *testing.T) { // Initialize this properly in a real test, // usually via secrets.NewTestSecrets. var store *secrets.Store ctx, cancel := context.WithCancel(context.Background()) t.Cleanup(cancel) processor := baseplatethrift.NewBaseplateServiceV2Processor(mockedBaseplateService{}) server, err := thrifttest.NewBaseplateServer(thrifttest.ServerConfig{ Processor: processor, SecretStore: store, }) if err != nil { t.Fatal(err) } // cancelling the context will close the server. server.Start(ctx) client := baseplatethrift.NewBaseplateServiceV2Client(server.ClientPool.TClient()) got, err := client.IsHealthy(ctx, &baseplatethrift.IsHealthyRequest{ Probe: baseplatethrift.IsHealthyProbePtr(baseplatethrift.IsHealthyProbe_READINESS), }) if err != nil { t.Errorf("expected no error, got %v", err) } const want = true if got != want { t.Errorf("success mismatch, want %v, got %v", want, got) } } // This example demonstrates how to write an unit test with mocked thrift server // using NewBaseplateServer. func main() { // The real example is in ServiceTest function. }
Output:
func (*Server) Close ¶ added in v0.2.1
Close the underying Server and Baseplate as well as the thriftbp.ClientPool.
func (*Server) Start ¶ added in v0.2.1
Start starts the server using baseplate.Serve in a background goroutine and waits for a short period of time to give the server time to start up.
The server can be shut down manually using server.Close, with the shutdown commands defined in runtimebp, or by cancelling the given context.
type ServerConfig ¶ added in v0.2.1
type ServerConfig struct { // Required, the processor to handle endpoints. Processor thrift.TProcessor // Required, the secret store. SecretStore *secrets.Store // ServerConfig is an optional value, sane defaults will be chosen where // appropriate. // // ServerConfig.Socket will always be replaced with one created in // NewBaseplateServer using the local loopback address. ServerConfig baseplate.Config // ClientConfig is an optional value, sane defaults will be chosen where // appropriate. // // Addr will always be set to the address of the test server. ClientConfig thriftbp.ClientPoolConfig // Optional, additional ClientMiddleware to wrap the client with. ClientMiddlewares []thrift.ClientMiddleware // Optional, additional ProcessorMiddleware to wrap the server with. ProcessorMiddlewares []thrift.ProcessorMiddleware // Optional, the ErrorSpanSuppressor used to create InjectServerSpan // middleware. ErrorSpanSuppressor errorsbp.Suppressor // Optional, the edge context implementation. // // If it's not set, ecinterface.Mock() will be used instead. EdgeContextImpl ecinterface.Interface }
ServerConfig can be used to pass in custom configuration options for the server and/or client created by NewBaseplateServer.