Giter Club home page Giter Club logo

mock-http-api's Introduction

mock-http-api PkgGoDev

Go helpers for mocking an HTTP API using stretchr/testify/mock

Library Usage

package mock_test

import (
   "encoding/json"
   "net/http"
   "testing"
   
   mockapi "github.com/mkeeler/mock-http-api"
)

// This test will pass as all the requisite API calls are made.
func TestMyAPI(t *testing.T) {
   m := mockapi.NewMockAPI(t)

   // http.Get will add both of the headers but we don't want to care about them.
   m.SetFilteredHeaders([]string{
      "Accept-Encoding",
      "User-Agent",
   })
      
   // This sets up an expectation that a GET request to /my/endpoint will be made and that it should
   // return a 200 status code with the provided map sent back JSON encoded as the body of the response
   call := m.WithJSONReply(mockapi.NewMockRequest("GET", "/my/endpoint"), 200, map[string]string{
      "foo": "bar",
   })
      
   // This sets the call to be required to happen exactly once
   call.Once()
      
   // This makes the HTTP request to the mock HTTP server. The mock api server exposes a URL()
   // method which will return a string of the form http://<ip>:<port> that you can use to make requests.
   // Typically this bit of code below would be replaced with invocation of some function that uses
   // your API
   resp, err := http.Get(fmt.Sprintf("%s/my/endpoint", m.URL()))
   if err != nil {
      t.Fatalf("Error issuing GET of /my/endpoint: %v", err)
   }

   defer resp.Body.Close()
   dec := json.NewDecoder(resp.Body)

   var output map[string]string
   if err := dec.Decode(&output); err != nil {
      t.Fatalf("Error decoding response: %v", err)
   }
      
   if val, ok := output["foo"]; !ok || val != "bar" {
      t.Fatalf("Didn't get the expected response")
   }
}

Code Generation

The code generator will create a new mock API type with helper methods for all the desired endpoints. These helpers are meant to be more ergonomic to use that the raw mock-http-api module itself.

Installing the code generator

go get github.com/mkeeler/mock-http-api/cmd/mock-api-gen

Note that you may need to run this command with GO111MODULE=on if executing outside of your GOPATH

Using mock-api-gen

mock-api-gen -type MockMyAPI -endpoints ./endpoints.json -pkg myapi -output api.helpers.go

This command will take in the JSON file of endpoints and generate the desired type with helpers for mocking responses to each API. See endpoint options to view the list of available options to configure mocked endpoints.

The format of the endpoints file is:

{
  "Endpoints": {
    "UpdateResource": {
      "Method": "POST",
      "Path": "/resource/%s",
      "PathParameters": ["resourceID"],
      "BodyFormat": "json",
      "ResponseFormat": "json",
      "Headers": true,
      "QueryParams": false
    }
  }
}

Using this as input the following file would be generated:

// Code generated by "mock-expect-gen -type MockAPI -pkg fakeapi -endpoints endpoints.json -output ./api.go"; DO NOT EDIT.

package fakeapi

import (
   "fmt"
   mockapi "github.com/mkeeler/mock-http-api"
)

type MockAPI struct {
   *mockapi.MockAPI
}

func NewMockAPI(t mockapi.TestingT) *MockAPI {
   return &MockAPI{
      MockAPI: mockapi.NewMockAPI(t),
   }
}

func (m *MockConsulAPI) UpdateResource(resourceID string, headers map[string]string, body map[string]interface{}, status int, reply interface{}) *mockapi.MockAPICall {
   req := mockapi.NewMockRequest("POST", fmt.Sprintf("/resource/%s", resourceID)).WithBody(body).WithHeaders(headers)

   return m.WithJSONReply(req, status, reply)
}

Then when you want to use this you would:

func TestFakeAPI(t *testing.T) {
   m := fakeapi.NewMockAPI(t)
   
   // Not necessary when the `t` passed into NewMockAPI supports a Cleanup method. (such as with the Go 1.14 testing.T type)
   defer m.Close()
   
   m.UpdateResource("some-id-here", 
      nil, 
      map[string]interface{"abc", "def"}, 
      200, 
      map[string]interface{"abc", "def", "added": true})
   
   httpServerURL := m.URL()
   
   // do something to cause the HTTP API call to happen here.
   
   // nothing else is necessary. Either the deferred m.Close or the automatic testing cleanup 
   // will assert that the required API calls were made.
}

Endpoint Options

Endpoint options for generating method signatures:

Argument Type Description
Method string The HTTP method for the endpoint.
Path string The path of the endpoint. Include string format verbs to represent path parameters (/v1/resource/%s).
PathParameters []string List of path parameters of the endpoint.
BodyFormat string The format of the body expected for the HTTP request. For example, none, json, string, stream.
BodyType string A string describing the go type for the method signature to include the typed representation of the request body. The default type is map[string]interface{}. Custom types from other packages, like *api.Resource, are supported. This requires the package to be specified in order to be properly imported. See import options for more information.
QueryParams bool This includes the option for mocking API query params in the method signature with the type map[string]string.
Headers bool This includes the option for HTTP headers for the request in the method signature with the type map[string]string.
ResponseFormat string The format of the response body returned: none, json, string, stream, func.
ResponseType string A string describing the go type for the method signature to include the typed representation of the response body. The default type is interface{}. Custom types from other packages, like *api.Resource, are supported. This requires the package to be specified in order to be properly imported. See import options for more information.

Import Options

To include custom types in the method signature for strict type checking, specify the import package in the endpoints file.

{
  "Imports": {
    "api": "github.com/namespace/project/path/api"
  },
  "Endpoints": {
    "ListResource": {
      "Method": "GET",
      "Path": "/resources",
      "ResponseFormat": "json",
      "ResponseType": "[]*api.Resource"
    }
  }
}

Full Usage

Usage of mock-api-gen:
        mock-api-gen [flags] -type <type name> -endpoints <var name> [package]
Flags:
  -endpoints string
        File holding the endpoint configuration. (default "endpoints")
  -output string
        Output file name.
  -pkg string
        Name of the package to generate methods in
  -tag value
        Build tags the generated file should have. This may be specified multiple times.
  -type string
        Method receiver type the mock API helpers should be generated for

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.