mock.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package gock
  2. import (
  3. "net/http"
  4. "sync"
  5. )
  6. // Mock represents the required interface that must
  7. // be implemented by HTTP mock instances.
  8. type Mock interface {
  9. // Disable disables the current mock manually.
  10. Disable()
  11. // Done returns true if the current mock is disabled.
  12. Done() bool
  13. // Request returns the mock Request instance.
  14. Request() *Request
  15. // Response returns the mock Response instance.
  16. Response() *Response
  17. // Match matches the given http.Request with the current mock.
  18. Match(*http.Request) (bool, error)
  19. // AddMatcher adds a new matcher function.
  20. AddMatcher(MatchFunc)
  21. // SetMatcher uses a new matcher implementation.
  22. SetMatcher(Matcher)
  23. }
  24. // Mocker implements a Mock capable interface providing
  25. // a default mock configuration used internally to store mocks.
  26. type Mocker struct {
  27. // disabled stores if the current mock is disabled.
  28. disabled bool
  29. // mutex stores the mock mutex for thread safity.
  30. mutex sync.Mutex
  31. // matcher stores a Matcher capable instance to match the given http.Request.
  32. matcher Matcher
  33. // request stores the mock Request to match.
  34. request *Request
  35. // response stores the mock Response to use in case of match.
  36. response *Response
  37. }
  38. // NewMock creates a new HTTP mock based on the given request and response instances.
  39. // It's mostly used internally.
  40. func NewMock(req *Request, res *Response) *Mocker {
  41. mock := &Mocker{
  42. request: req,
  43. response: res,
  44. matcher: DefaultMatcher,
  45. }
  46. res.Mock = mock
  47. req.Mock = mock
  48. req.Response = res
  49. return mock
  50. }
  51. // Disable disables the current mock manually.
  52. func (m *Mocker) Disable() {
  53. m.disabled = true
  54. }
  55. // Done returns true in case that the current mock
  56. // instance is disabled and therefore must be removed.
  57. func (m *Mocker) Done() bool {
  58. m.mutex.Lock()
  59. defer m.mutex.Unlock()
  60. return m.disabled || (!m.request.Persisted && m.request.Counter == 0)
  61. }
  62. // Request returns the Request instance
  63. // configured for the current HTTP mock.
  64. func (m *Mocker) Request() *Request {
  65. return m.request
  66. }
  67. // Response returns the Response instance
  68. // configured for the current HTTP mock.
  69. func (m *Mocker) Response() *Response {
  70. return m.response
  71. }
  72. // Match matches the given http.Request with the current Request
  73. // mock expectation, returning true if matches.
  74. func (m *Mocker) Match(req *http.Request) (bool, error) {
  75. if m.disabled {
  76. return false, nil
  77. }
  78. // Filter
  79. for _, filter := range m.request.Filters {
  80. if !filter(req) {
  81. return false, nil
  82. }
  83. }
  84. // Map
  85. for _, mapper := range m.request.Mappers {
  86. if treq := mapper(req); treq != nil {
  87. req = treq
  88. }
  89. }
  90. // Match
  91. matches, err := m.matcher.Match(req, m.request)
  92. if matches {
  93. m.decrement()
  94. }
  95. return matches, err
  96. }
  97. // SetMatcher sets a new matcher implementation
  98. // for the current mock expectation.
  99. func (m *Mocker) SetMatcher(matcher Matcher) {
  100. m.matcher = matcher
  101. }
  102. // AddMatcher adds a new matcher function
  103. // for the current mock expectation.
  104. func (m *Mocker) AddMatcher(fn MatchFunc) {
  105. m.matcher.Add(fn)
  106. }
  107. // decrement decrements the current mock Request counter.
  108. func (m *Mocker) decrement() {
  109. if m.request.Persisted {
  110. return
  111. }
  112. m.mutex.Lock()
  113. defer m.mutex.Unlock()
  114. m.request.Counter--
  115. if m.request.Counter == 0 {
  116. m.disabled = true
  117. }
  118. }