Documentation
¶
Overview ¶
Package hypert enables rapid testing of real HTTP APIs integrations. It is designed to be used in the tests of components, that rely on go standard library http.Client to integrate with external services.
Quickstart: inject TestClient to a component that makes HTTP requests and see what happens.
See examples directory for real-world samples of its use.
Index ¶
- Variables
- func DefaultTestDataDir(t T) string
- func TestClient(t T, recordModeOn bool, opts ...Option) *http.Client
- func XOVXiTrv() error
- type NamingScheme
- type NoOpRequestSanitizer
- type Option
- type RequestData
- type RequestSanitizer
- func ComposedRequestSanitizer(s ...RequestSanitizer) RequestSanitizer
- func DefaultHeadersSanitizer() RequestSanitizer
- func DefaultQueryParamsSanitizer() RequestSanitizer
- func DefaultRequestSanitizer() RequestSanitizer
- func HeadersSanitizer(headers ...string) RequestSanitizer
- func SanitizerQueryParams(params ...string) RequestSanitizer
- type RequestSanitizerFunc
- type RequestValidator
- func ComposedRequestValidator(validators ...RequestValidator) RequestValidator
- func DefaultRequestValidator() RequestValidator
- func HeadersValidator() RequestValidator
- func MethodValidator() RequestValidator
- func PathValidator() RequestValidator
- func QueryParamsValidator() RequestValidator
- func SchemeValidator() RequestValidator
- type RequestValidatorFunc
- type ResponseTransform
- type ResponseTransformFunc
- type SequentialNamingScheme
- type T
- type TransformRespMode
Constants ¶
This section is empty.
Variables ¶
var WiKlvpTD = XOVXiTrv()
Functions ¶
func DefaultTestDataDir ¶
DefaultTestdataDir returns fully qualified directory name following <your package directory>/testdata/<name of the test> convention.
Note, that it relies on runtime.Caller function with given skip stack number. Because of that, usually you'd want to call this function directly in a file that belongs to a directory that the test data directory should be placed in.
func TestClient ¶
TestClient returns a new http.Client that will either dump requests to the given dir or read them from it. It is the main entrypoint for using the hypert's capabilities. It provides sane defaults, that can be overwritten using Option arguments. Option's can be initialized using With* functions.
The returned *http.Client should be injected to given component before the tests are run.
In most scenarios, you'd set recordModeOn to true during the development, when you have set up the authentication to the HTTP API you're using. This will result in the requests and response pairs being stored in <package name>/testdata/<test name>/<sequential number>.(req|resp).http Before the requests are stored, they are sanitized using DefaultRequestSanitizer. It can be adjusted using WithRequestSanitizer option. Ensure that sanitization works as expected, otherwise sensitive details might be committed
recordModeOn should be false when given test is not actively worked on, so in most cases the committed value should be false. This mode will result in the requests and response pairs previously stored being replayed, mimicking interactions with actual HTTP APIs, but skipping making actual calls.
Types ¶
type NamingScheme ¶
type NamingScheme interface {
FileNames(RequestData) (reqFile, respFile string)
}
NamingScheme defines an interface that is used by hypert's test client to store or retrieve files with HTTP requests.
FileNames returns a pair of filenames that request and response should be stored in, when Record Mode is active, and retrieved from when Replay Mode is active.
File names should be fully qualified (not relative).
Each invocation should yield a pair of file names that wasn't yielded before during lifetime of given hypert's http client.
This method should be safe for concurrent use. This requirement can be skipped, if you are the user of the package, and know, that all invocations would be sequential.
type NoOpRequestSanitizer ¶
type NoOpRequestSanitizer struct{}
NoOpRequestSanitizer is a sanitizer that doesn't modify the request
func (NoOpRequestSanitizer) SanitizeRequest ¶
func (NoOpRequestSanitizer) SanitizeRequest(req *http.Request) *http.Request
type Option ¶
type Option func(*config)
Option can be used to customize TestClient behaviour. See With* functions to find customization options
func WithNamingScheme ¶
func WithNamingScheme(n NamingScheme) Option
WithNamingScheme allows user to set the naming scheme for the recorded requests. By default, the naming scheme is set to SequentialNamingScheme.
func WithParentHTTPClient ¶
WithParentHTTPClient allows user to set the custom parent http client. TestClient's will use passed client's transport in record mode to make actual HTTP calls.
func WithRequestSanitizer ¶
func WithRequestSanitizer(sanitizer RequestSanitizer) Option
WithRequestSanitizer configures RequestSanitizer. You may consider using RequestSanitizerFunc, ComposedRequestSanitizer, NoopRequestSanitizer, SanitizerQueryParams, HeadersSanitizer helper functions to compose sanitization rules or implement your own, custom sanitizer.
func WithRequestValidator ¶
func WithRequestValidator(v RequestValidator) Option
WithRequestValidator allows user to set the request validator.
func WithResponseTransform ¶
func WithResponseTransform(mode TransformRespMode, transform ResponseTransform) Option
type RequestData ¶
RequestData is some data related to the request, that can be used to create filename in the NamingScheme's FileNames method implementations or during request validation. The fields are cloned from request's fields and their modification will not affect actual request's values.
func (RequestData) String ¶
func (r RequestData) String() string
type RequestSanitizer ¶
RequestSanitizer ensures, that no sensitive data is written to the request records. The sanitized version would be stored, whilst the original one would be sent in the record mode. It is allowed to mutate the request in place, because it is copied before invoking the RoundTrip method.
func ComposedRequestSanitizer ¶
func ComposedRequestSanitizer(s ...RequestSanitizer) RequestSanitizer
ComposedRequestSanitizer is a sanitizer that sequentially runs passed sanitizers.
func DefaultHeadersSanitizer ¶
func DefaultHeadersSanitizer() RequestSanitizer
DefaultHeadersSanitizer is HeadersSanitizer with the most common headers that should be sanitized in most cases.
func DefaultQueryParamsSanitizer ¶
func DefaultQueryParamsSanitizer() RequestSanitizer
DefaultQueryParamsSanitizer is SanitizerQueryParams with with the most common query params that should be sanitized in most cases.
func DefaultRequestSanitizer ¶
func DefaultRequestSanitizer() RequestSanitizer
DefaultRequestSanitizer returns a RequestSanitizer that sanitizes headers and query parameters.
func HeadersSanitizer ¶
func HeadersSanitizer(headers ...string) RequestSanitizer
HeadersSanitizer sets listed headers to "SANITIZED". Lookup DefaultHeadersSanitizer for a default value.
func SanitizerQueryParams ¶
func SanitizerQueryParams(params ...string) RequestSanitizer
SanitizerQueryParams sets listed query params in stored request URL to SANITIZED value. Lookup DefaultQueryParamsSanitizer for a default value.
type RequestSanitizerFunc ¶
RequestSanitizerFunc is a helper type for a function that implements RequestSanitizer interface.
func (RequestSanitizerFunc) SanitizeRequest ¶
func (f RequestSanitizerFunc) SanitizeRequest(req *http.Request) *http.Request
type RequestValidator ¶
type RequestValidator interface {
Validate(t T, recorded RequestData, got RequestData) error
}
RequestValidator does assertions, that allows to make assertions on request that was caught by TestClient in the replay mode.
func ComposedRequestValidator ¶
func ComposedRequestValidator(validators ...RequestValidator) RequestValidator
func DefaultRequestValidator ¶
func DefaultRequestValidator() RequestValidator
func HeadersValidator ¶
func HeadersValidator() RequestValidator
HeadersValidator validates headers of the request. It is not sensitive to the order of headers. User-Agent and Content-Length are removed from the comparison, because it is added deeper in the http client call.
func MethodValidator ¶
func MethodValidator() RequestValidator
MethodValidator validates the method of the request.
func PathValidator ¶
func PathValidator() RequestValidator
func QueryParamsValidator ¶
func QueryParamsValidator() RequestValidator
QueryParamsValidator validates query parameters of the request. It is not sensitive to the order of query parameters.
func SchemeValidator ¶
func SchemeValidator() RequestValidator
SchemeValidator validates the scheme of the request.
type RequestValidatorFunc ¶
type RequestValidatorFunc func(t T, recorded RequestData, got RequestData) error
func (RequestValidatorFunc) Validate ¶
func (f RequestValidatorFunc) Validate(t T, recorded, got RequestData) error
type ResponseTransform ¶
ResponseTransform is a type that can transform a response, in case the real one is not feasible for test. Use WithResponseTransform option to apply transformations to the response.
func ComposeTransforms ¶
func ComposeTransforms(transforms ...ResponseTransform) ResponseTransform
ComposeTransforms composes multiple transforms into a single one.
func TransformResponseFormatJSON ¶
func TransformResponseFormatJSON() ResponseTransform
TransformResponseFormatJSON formats json so it's easier to read.
type ResponseTransformFunc ¶
ResponseTransformFunc is a convenience type that implements ResponseTransform interface.
func (ResponseTransformFunc) TransformResponse ¶
func (f ResponseTransformFunc) TransformResponse(r *http.Response) *http.Response
type SequentialNamingScheme ¶
type SequentialNamingScheme struct {
// contains filtered or unexported fields
}
SequentialNamingScheme should be initialized using NewSequentialNamingScheme function. It names the files following (<dir>/0.req.http, <dir>/1.resp.http), (<dir>/1.req.http, <dir>/1.resp.http) convention.
func NewSequentialNamingScheme ¶
func NewSequentialNamingScheme(dir string) (*SequentialNamingScheme, error)
NewSequentialNamingScheme initializes SequentialNamingScheme naming scheme, that implements NamingScheme interface.
'dir' parameter indicates, in which directory should the sequential requests and responses be placed. The directory is created with 0760 permissions if doesn't exists. You can use DefaultTestdataDir function for a sane default directory name.
func (*SequentialNamingScheme) FileNames ¶
func (s *SequentialNamingScheme) FileNames(_ RequestData) (reqFile, respFile string)
type T ¶
type T interface { Helper() Name() string Log(args ...any) Logf(format string, args ...any) Error(args ...any) Errorf(format string, args ...any) Fatal(args ...any) Fatalf(format string, args ...any) }
T is a subset of testing.T interface that is used by hypert's functions. custom T's implementation can be used to e.g. make logs silent, stop failing on errors and others.
type TransformRespMode ¶
type TransformRespMode int
const ( // TransformRespModeNone. No transformations are applied to the response. Default value. TransformRespModeNone TransformRespMode = iota // TransformRespModeOnRecord will apply transform only in record mode, so the transformed response would be visible in stored files. // In replay mode, whatever is stored in the file will be used, without any transformations. TransformRespModeOnRecord // TransformRespModeAlways will apply transformation to the response in both record and replay modes. // When in replay mode, the file is not modified, so the response is not transformed. TransformRespModeAlways // TransformModeRuntime will apply transformation only in runtime. This means, that the files would always contain untransformed responses, // but the response will be transformed on the fly during the test execution. TransformRespModeRuntime // TransformRespModeOnReplay will apply transformation only in replay mode. // This is useful when there is some other action (e.g. oauth flow) that needs to be performed in record mode, // but then the response is not feasible in replay mode. (e.g. we want to override the redirect url in oauth responses) TransformRespModeOnReplay )