From c87e9528063c570d0082ca0e282f23ccb36c168d Mon Sep 17 00:00:00 2001 From: "andrey.suchilov" Date: Thu, 1 Dec 2022 14:06:37 +0300 Subject: [PATCH] the ability to create custom mock services --- go.mod | 7 +++-- go.sum | 15 +++------ mocks/definition.go | 20 ++++++------ mocks/loader.go | 52 ++++++++++++++++---------------- mocks/mocks.go | 6 +++- mocks/reply_strategy.go | 22 +++++++------- mocks/service_mock.go | 8 ++--- mocks/template_reply_strategy.go | 2 +- 8 files changed, 66 insertions(+), 66 deletions(-) diff --git a/go.mod b/go.mod index 35d8cae..563e286 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,8 @@ require ( github.com/Masterminds/sprig/v3 v3.2.2 github.com/aerospike/aerospike-client-go/v5 v5.8.0 github.com/fatih/color v1.7.0 - github.com/go-redis/redis/v9 v9.0.0-beta.2 // indirect + github.com/go-redis/redis/v9 v9.0.0-beta.2 + github.com/google/go-cmp v0.5.8 github.com/google/uuid v1.1.1 github.com/huandu/xstrings v1.3.2 // indirect github.com/imdario/mergo v0.3.13 // indirect @@ -14,8 +15,8 @@ require ( github.com/kylelemons/godebug v1.1.0 github.com/lib/pq v1.3.0 github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/onsi/ginkgo v1.16.5 // indirect github.com/stretchr/testify v1.7.1 github.com/tidwall/gjson v1.13.0 github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 // indirect @@ -23,5 +24,5 @@ require ( golang.org/x/sync v0.0.0-20210220032951-036812b2e83c gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 gopkg.in/yaml.v2 v2.4.0 - gopkg.in/yaml.v3 v3.0.1 // indirect + gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index b288ac5..ee84349 100644 --- a/go.sum +++ b/go.sum @@ -37,7 +37,6 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -60,8 +59,9 @@ github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= @@ -76,7 +76,6 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= @@ -84,7 +83,6 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= @@ -132,7 +130,6 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -163,11 +160,11 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -183,7 +180,6 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -192,8 +188,8 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw= @@ -208,7 +204,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0 h1:hjy8E9ON/egN1tAYqKb61G10WtihqetD4sz2H+8nIeA= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/mocks/definition.go b/mocks/definition.go index 125af31..19c18ec 100644 --- a/mocks/definition.go +++ b/mocks/definition.go @@ -7,19 +7,19 @@ import ( "sync" ) -const callsNoConstraint = -1 +const CallsNoConstraint = -1 -type definition struct { +type Definition struct { path string requestConstraints []verifier - replyStrategy replyStrategy + replyStrategy ReplyStrategy sync.Mutex calls int callsConstraint int } -func newDefinition(path string, constraints []verifier, strategy replyStrategy, callsConstraint int) *definition { - return &definition{ +func NewDefinition(path string, constraints []verifier, strategy ReplyStrategy, callsConstraint int) *Definition { + return &Definition{ path: path, requestConstraints: constraints, replyStrategy: strategy, @@ -27,7 +27,7 @@ func newDefinition(path string, constraints []verifier, strategy replyStrategy, } } -func (d *definition) Execute(w http.ResponseWriter, r *http.Request) []error { +func (d *Definition) Execute(w http.ResponseWriter, r *http.Request) []error { d.Lock() d.calls++ d.Unlock() @@ -55,7 +55,7 @@ func (d *definition) Execute(w http.ResponseWriter, r *http.Request) []error { return errors } -func (d *definition) ResetRunningContext() { +func (d *Definition) ResetRunningContext() { if s, ok := d.replyStrategy.(contextAwareStrategy); ok { s.ResetRunningContext() } @@ -64,14 +64,14 @@ func (d *definition) ResetRunningContext() { d.Unlock() } -func (d *definition) EndRunningContext() []error { +func (d *Definition) EndRunningContext() []error { d.Lock() defer d.Unlock() var errs []error if s, ok := d.replyStrategy.(contextAwareStrategy); ok { errs = s.EndRunningContext() } - if d.callsConstraint != callsNoConstraint && d.calls != d.callsConstraint { + if d.callsConstraint != CallsNoConstraint && d.calls != d.callsConstraint { err := fmt.Errorf("at path %s: number of calls does not match: expected %d, actual %d", d.path, d.callsConstraint, d.calls) errs = append(errs, err) @@ -99,7 +99,7 @@ func verifyRequestConstraints(requestConstraints []verifier, r *http.Request) [] } return errors } -func (d *definition) ExecuteWithoutVerifying(w http.ResponseWriter, r *http.Request) []error { +func (d *Definition) ExecuteWithoutVerifying(w http.ResponseWriter, r *http.Request) []error { d.Lock() d.calls++ d.Unlock() diff --git a/mocks/loader.go b/mocks/loader.go index 499ff7a..cb78c64 100644 --- a/mocks/loader.go +++ b/mocks/loader.go @@ -27,18 +27,18 @@ func (l *Loader) Load(mocksDefinition map[string]interface{}) error { } def, err := l.loadDefinition("$", definition) if err != nil { - return fmt.Errorf("unable to load definition for %s: %v", serviceName, err) + return fmt.Errorf("unable to load Definition for %s: %v", serviceName, err) } - // load the definition into the mock + // load the Definition into the mock service.SetDefinition(def) } return nil } -func (l *Loader) loadDefinition(path string, rawDef interface{}) (*definition, error) { +func (l *Loader) loadDefinition(path string, rawDef interface{}) (*Definition, error) { def, ok := rawDef.(map[interface{}]interface{}) if !ok { - return nil, fmt.Errorf("at path %s: definition must be key-values", path) + return nil, fmt.Errorf("at path %s: Definition must be key-values", path) } // load request constraints @@ -78,7 +78,7 @@ func (l *Loader) loadDefinition(path string, rawDef interface{}) (*definition, e return nil, err } - callsConstraint := callsNoConstraint + callsConstraint := CallsNoConstraint if _, ok = def["calls"]; ok { if value, ok := def["calls"].(int); ok { callsConstraint = value @@ -89,10 +89,10 @@ func (l *Loader) loadDefinition(path string, rawDef interface{}) (*definition, e return nil, err } - return newDefinition(path, requestConstraints, replyStrategy, callsConstraint), nil + return NewDefinition(path, requestConstraints, replyStrategy, callsConstraint), nil } -func (l *Loader) loadStrategy(path, strategyName string, definition map[interface{}]interface{}, ak *[]string) (replyStrategy, error) { +func (l *Loader) loadStrategy(path, strategyName string, definition map[interface{}]interface{}, ak *[]string) (ReplyStrategy, error) { switch strategyName { case "nop": return &nopReply{}, nil @@ -122,18 +122,18 @@ func (l *Loader) loadStrategy(path, strategyName string, definition map[interfac } } -func (l *Loader) loadUriVaryStrategy(path string, def map[interface{}]interface{}) (replyStrategy, error) { +func (l *Loader) loadUriVaryStrategy(path string, def map[interface{}]interface{}) (ReplyStrategy, error) { var basePath string if b, ok := def["basePath"]; ok { basePath = b.(string) } - var uris map[string]*definition + var uris map[string]*Definition if u, ok := def["uris"]; ok { urisMap, ok := u.(map[interface{}]interface{}) if !ok { return nil, errors.New("`uriVary` requires map under `uris` key") } - uris = make(map[string]*definition, len(urisMap)) + uris = make(map[string]*Definition, len(urisMap)) for uri, v := range urisMap { def, err := l.loadDefinition(path+"."+uri.(string), v) if err != nil { @@ -142,17 +142,17 @@ func (l *Loader) loadUriVaryStrategy(path string, def map[interface{}]interface{ uris[uri.(string)] = def } } - return newUriVaryReply(basePath, uris), nil + return NewUriVaryReply(basePath, uris), nil } -func (l *Loader) loadMethodVaryStrategy(path string, def map[interface{}]interface{}) (replyStrategy, error) { - var methods map[string]*definition +func (l *Loader) loadMethodVaryStrategy(path string, def map[interface{}]interface{}) (ReplyStrategy, error) { + var methods map[string]*Definition if u, ok := def["methods"]; ok { methodsMap, ok := u.(map[interface{}]interface{}) if !ok { return nil, errors.New("`methodVary` requires map under `methods` key") } - methods = make(map[string]*definition, len(methodsMap)) + methods = make(map[string]*Definition, len(methodsMap)) for method, v := range methodsMap { def, err := l.loadDefinition(path+"."+method.(string), v) if err != nil { @@ -161,10 +161,10 @@ func (l *Loader) loadMethodVaryStrategy(path string, def map[interface{}]interfa methods[method.(string)] = def } } - return newMethodVaryReply(methods), nil + return NewMethodVaryReply(methods), nil } -func (l *Loader) loadFileStrategy(path string, def map[interface{}]interface{}) (replyStrategy, error) { +func (l *Loader) loadFileStrategy(path string, def map[interface{}]interface{}) (ReplyStrategy, error) { f, ok := def["filename"] if !ok { return nil, errors.New("`file` requires `filename` key") @@ -181,10 +181,10 @@ func (l *Loader) loadFileStrategy(path string, def map[interface{}]interface{}) if err != nil { return nil, err } - return newFileReplyWithCode(filename, statusCode, headers) + return NewFileReplyWithCode(filename, statusCode, headers) } -func (l *Loader) loadConstantStrategy(path string, def map[interface{}]interface{}) (replyStrategy, error) { +func (l *Loader) loadConstantStrategy(path string, def map[interface{}]interface{}) (ReplyStrategy, error) { c, ok := def["body"] if !ok { return nil, errors.New("`constant` requires `body` key") @@ -201,10 +201,10 @@ func (l *Loader) loadConstantStrategy(path string, def map[interface{}]interface if err != nil { return nil, err } - return newConstantReplyWithCode([]byte(body), statusCode, headers), nil + return NewConstantReplyWithCode([]byte(body), statusCode, headers), nil } -func (l *Loader) loadTemplateStrategy(path string, def map[interface{}]interface{}) (replyStrategy, error) { +func (l *Loader) loadTemplateStrategy(path string, def map[interface{}]interface{}) (ReplyStrategy, error) { c, ok := def["body"] if !ok { return nil, errors.New("`template` requires `body` key") @@ -224,7 +224,7 @@ func (l *Loader) loadTemplateStrategy(path string, def map[interface{}]interface return newTemplateReply(body, statusCode, headers) } -func (l *Loader) loadSequenceStrategy(path string, def map[interface{}]interface{}) (replyStrategy, error) { +func (l *Loader) loadSequenceStrategy(path string, def map[interface{}]interface{}) (ReplyStrategy, error) { if _, ok := def["sequence"]; !ok { return nil, errors.New("`sequence` requires `sequence` key") } @@ -232,7 +232,7 @@ func (l *Loader) loadSequenceStrategy(path string, def map[interface{}]interface if !ok { return nil, errors.New("`sequence` must be a list") } - strategies := make([]*definition, len(seqSlice)) + strategies := make([]*Definition, len(seqSlice)) for i, v := range seqSlice { def, err := l.loadDefinition(path+"."+strconv.Itoa(i), v) if err != nil { @@ -240,17 +240,17 @@ func (l *Loader) loadSequenceStrategy(path string, def map[interface{}]interface } strategies[i] = def } - return newSequentialReply(strategies), nil + return NewSequentialReply(strategies), nil } -func (l *Loader) loadBasedOnRequestStrategy(path string, def map[interface{}]interface{}) (replyStrategy, error) { - var uris []*definition +func (l *Loader) loadBasedOnRequestStrategy(path string, def map[interface{}]interface{}) (ReplyStrategy, error) { + var uris []*Definition if u, ok := def["uris"]; ok { urisList, ok := u.([]interface{}) if !ok { return nil, errors.New("`basedOnRequest` requires list under `uris` key") } - uris = make([]*definition, 0, len(urisList)) + uris = make([]*Definition, 0, len(urisList)) for i, v := range urisList { v, ok := v.(map[interface{}]interface{}) if !ok { diff --git a/mocks/mocks.go b/mocks/mocks.go index 6312a5d..383634f 100644 --- a/mocks/mocks.go +++ b/mocks/mocks.go @@ -24,7 +24,7 @@ func New(mocks ...*ServiceMock) *Mocks { func NewNop(serviceNames ...string) *Mocks { mocksMap := make(map[string]*ServiceMock, len(serviceNames)) for _, name := range serviceNames { - mocksMap[name] = NewServiceMock(name, newDefinition("$", nil, &failReply{}, callsNoConstraint)) + mocksMap[name] = NewServiceMock(name, NewDefinition("$", nil, &failReply{}, CallsNoConstraint)) } return &Mocks{ mocks: mocksMap, @@ -68,6 +68,10 @@ func (m *Mocks) ShutdownContext(ctx context.Context) error { return nil } +func (m *Mocks) SetMock(mock *ServiceMock) { + m.mocks[mock.ServiceName] = mock +} + func (m *Mocks) Service(serviceName string) *ServiceMock { mock, _ := m.mocks[serviceName] return mock diff --git a/mocks/reply_strategy.go b/mocks/reply_strategy.go index 18634ee..4a08981 100644 --- a/mocks/reply_strategy.go +++ b/mocks/reply_strategy.go @@ -9,7 +9,7 @@ import ( "sync" ) -type replyStrategy interface { +type ReplyStrategy interface { HandleRequest(w http.ResponseWriter, r *http.Request) []error } @@ -32,7 +32,7 @@ func unhandledRequestError(r *http.Request) []error { return []error{fmt.Errorf("unhandled request to mock:\n%s", requestContent)} } -func newFileReplyWithCode(filename string, statusCode int, headers map[string]string) (replyStrategy, error) { +func NewFileReplyWithCode(filename string, statusCode int, headers map[string]string) (ReplyStrategy, error) { content, err := ioutil.ReadFile(filename) if err != nil { return nil, err @@ -45,7 +45,7 @@ func newFileReplyWithCode(filename string, statusCode int, headers map[string]st return r, nil } -func newConstantReplyWithCode(content []byte, statusCode int, headers map[string]string) replyStrategy { +func NewConstantReplyWithCode(content []byte, statusCode int, headers map[string]string) ReplyStrategy { return &constantReply{ replyBody: content, statusCode: statusCode, @@ -77,10 +77,10 @@ func (s *nopReply) HandleRequest(w http.ResponseWriter, r *http.Request) []error type uriVaryReply struct { basePath string - variants map[string]*definition + variants map[string]*Definition } -func newUriVaryReply(basePath string, variants map[string]*definition) replyStrategy { +func NewUriVaryReply(basePath string, variants map[string]*Definition) ReplyStrategy { return &uriVaryReply{ basePath: strings.TrimRight(basePath, "/") + "/", variants: variants, @@ -112,10 +112,10 @@ func (s *uriVaryReply) EndRunningContext() []error { } type methodVaryReply struct { - variants map[string]*definition + variants map[string]*Definition } -func newMethodVaryReply(variants map[string]*definition) replyStrategy { +func NewMethodVaryReply(variants map[string]*Definition) ReplyStrategy { return &methodVaryReply{ variants: variants, } @@ -144,7 +144,7 @@ func (s *methodVaryReply) EndRunningContext() []error { return errs } -func newSequentialReply(strategies []*definition) replyStrategy { +func NewSequentialReply(strategies []*Definition) ReplyStrategy { return &sequentialReply{ sequence: strategies, } @@ -153,7 +153,7 @@ func newSequentialReply(strategies []*definition) replyStrategy { type sequentialReply struct { sync.Mutex count int - sequence []*definition + sequence []*Definition } func (s *sequentialReply) ResetRunningContext() { @@ -187,10 +187,10 @@ func (s *sequentialReply) HandleRequest(w http.ResponseWriter, r *http.Request) type basedOnRequestReply struct { sync.Mutex - variants []*definition + variants []*Definition } -func newBasedOnRequestReply(variants []*definition) replyStrategy { +func newBasedOnRequestReply(variants []*Definition) ReplyStrategy { return &basedOnRequestReply{ variants: variants, } diff --git a/mocks/service_mock.go b/mocks/service_mock.go index c0b32eb..99d345d 100644 --- a/mocks/service_mock.go +++ b/mocks/service_mock.go @@ -10,15 +10,15 @@ import ( type ServiceMock struct { server *http.Server listener net.Listener - mock *definition - defaultDefinition *definition + mock *Definition + defaultDefinition *Definition sync.RWMutex errors []error ServiceName string } -func NewServiceMock(serviceName string, mock *definition) *ServiceMock { +func NewServiceMock(serviceName string, mock *Definition) *ServiceMock { return &ServiceMock{ mock: mock, defaultDefinition: mock, @@ -65,7 +65,7 @@ func (m *ServiceMock) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } -func (m *ServiceMock) SetDefinition(newDefinition *definition) { +func (m *ServiceMock) SetDefinition(newDefinition *Definition) { m.Lock() defer m.Unlock() m.mock = newDefinition diff --git a/mocks/template_reply_strategy.go b/mocks/template_reply_strategy.go index 7b74633..1039f8a 100644 --- a/mocks/template_reply_strategy.go +++ b/mocks/template_reply_strategy.go @@ -41,7 +41,7 @@ func (tr *templateRequest) Json() (map[string]interface{}, error) { return tr.jsonData, nil } -func newTemplateReply(content string, statusCode int, headers map[string]string) (replyStrategy, error) { +func newTemplateReply(content string, statusCode int, headers map[string]string) (ReplyStrategy, error) { tmpl, err := template.New("").Funcs(sprig.GenericFuncMap()).Parse(content) if err != nil { return nil, fmt.Errorf("template syntax error: %w", err)