• Stars
    star
    1,096
  • Rank 40,690 (Top 0.9 %)
  • Language
    Go
  • License
    BSD 2-Clause "Sim...
  • Created over 8 years ago
  • Updated 8 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Record and replay your HTTP interactions for fast, deterministic and accurate tests

go-vcr

Build Status Go Reference Go Report Card codecov

go-vcr simplifies testing by recording your HTTP interactions and replaying them in future runs in order to provide fast, deterministic and accurate testing of your code.

go-vcr was inspired by the VCR library for Ruby.

Installation

Install go-vcr by executing the command below:

$ go get -v gopkg.in/dnaeon/go-vcr.v3/recorder

Note, that if you are migrating from a previous version of go-vcr, you need re-create your test cassettes, because as of go-vcr v3 there is a new format of the cassette, which is not backwards-compatible with older releases.

Usage

Please check the examples from this repo for example usage of go-vcr.

You can also refer to the test cases for additional examples.

Custom Request Matching

During replay mode, You can customize the way incoming requests are matched against the recorded request/response pairs by defining a MatcherFunc function.

For example, the following matcher will match on method, URL and body:

func customMatcher(r *http.Request, i cassette.Request) bool {
	if r.Body == nil || r.Body == http.NoBody {
		return cassette.DefaultMatcher(r, i)
	}

	var reqBody []byte
	var err error
	reqBody, err = io.ReadAll(r.Body)
	if err != nil {
		log.Fatal("failed to read request body")
	}
	r.Body.Close()
	r.Body = ioutil.NopCloser(bytes.NewBuffer(reqBody))

	return r.Method == i.Method && r.URL.String() == i.URL && string(reqBody) == i.Body
}

func recorderWithCustomMatcher() {
	rec, err := recorder.New("fixtures/matchers")
	if err != nil {
		log.Fatal(err)
	}
	defer rec.Stop() // Make sure recorder is stopped once done with it

	rec.SetReplayableInteractions(true)
	rec.SetMatcher(customMatcher)

	client := rec.GetDefaultClient()
	resp, err := client.Get("https://www.google.com/")
	...
	...
	...
}

Hooks

Hooks in go-vcr are regular functions which take an HTTP interaction and are invoked in different stages of the playback.

You can use hooks to modify a request/response before it is saved on disk, before it is returned to the client, or anything else that you might want to do with it, e.g. you might want to simply log each captured interaction.

You often provide sensitive data, such as API credentials, when making requests against a service.

By default, this data will be stored in the recorded data but you probably don't want this.

Removing or replacing data before it is stored can be done by adding one or more Hooks to your Recorder.

There are different kinds of hooks, which are invoked in different stages of the playback. The supported hook kinds are AfterCaptureHook, BeforeSaveHook and BeforeResponseReplayHook.

Here is an example that removes the Authorization header from all requests right after capturing a new interaction.

r, err := recorder.New("fixtures/filters")
if err != nil {
	log.Fatal(err)
}
defer r.Stop() // Make sure recorder is stopped once done with it

// Add a hook which removes Authorization headers from all requests
hook := func(i *cassette.Interaction) error {
	delete(i.Request.Headers, "Authorization")
	return nil
}
r.AddHook(hook, recorder.AfterCaptureHook)

Hooks added using recorder.AfterCaptureHook are applied right after an interaction is captured and added to the in-memory cassette. This may not always be what you need. For example if you modify an interaction using this hook kind then subsequent test code will see the edited response.

For instance, if a response body contains an OAuth access token that is needed for subsequent requests, then redacting the access token using a AfterCaptureHook will result in authorization failures in subsequent test code.

In such cases you would want to modify the recorded interactions right before they are saved on disk. For that purpose you should be using a BeforeSaveHook, e.g.

r, err := recorder.New("fixtures/filters")
if err != nil {
	log.Fatal(err)
}
defer r.Stop() // Make sure recorder is stopped once done with it

// Your test code will continue to see the real access token and
// it is redacted before the recorded interactions are saved on disk
hook := func(i *cassette.Interaction) error {
	if strings.Contains(i.Request.URL, "/oauth/token") {
		i.Response.Body = `{"access_token": "[REDACTED]"}`
	}

	return nil
}
r.AddHook(hook, recorder.BeforeSaveHook)

Passing Through Requests

Sometimes you want to allow specific requests to pass through to the remote server without recording anything.

Globally, you can use ModePassthrough for this, but if you want to disable the recorder for individual requests, you can add Passthrough handlers to the recorder.

The function takes a pointer to the original request, and returns a boolean, indicating if the request should pass through to the remote server.

Here's an example to pass through requests to a specific endpoint:

// Passthrough the request to the remote server if the path matches "/login".
r.AddPassthrough(func(req *http.Request) bool {
    return req.URL.Path == "/login"
})

License

go-vcr is Open Source and licensed under the BSD License

More Repositories

1

gru

Orchestration made easy with Go and Lua
Go
461
star
2

clingon

Command-line options parser system for Common Lisp
Common Lisp
112
star
3

py-vpoller

Distributed vSphere API Proxy
Python
82
star
4

zabbix-ldap-sync

Sync Zabbix with LDAP directory server
Python
73
star
5

makefile-graph

Turn your Makefile into a graph
Go
65
star
6

cl-covid19

Explore COVID-19 data with Common Lisp, gnuplot, SQL and Grafana
Common Lisp
58
star
7

py-vconnector

VMware vSphere Connector Module for Python
Python
49
star
8

cl-jingle

Common Lisp web framework with bells and whistles (based on ningle)
Common Lisp
46
star
9

pvc

Python vSphere Client with a dialog(1) interface
Python
46
star
10

cl-migratum

Database Schema Migration System for Common Lisp
Common Lisp
41
star
11

go-dependency-graph-algorithm

Dependency graph resolution algorithm in Go
Go
32
star
12

go-binarytree

A simple Binary Tree implementation in Go
Go
28
star
13

pytraceroute

A simple traceroute(8) implementation in Python
Python
28
star
14

go-priorityqueue

Simple and generic implementation of priority queues in Go
Go
22
star
15

cl-ssh-keys

Common Lisp system for generating and parsing of OpenSSH keys
Common Lisp
20
star
16

cl-jwk

Common Lisp system for decoding public JSON Web Keys (JWK)
Common Lisp
17
star
17

pyinfoblox

Infoblox WAPI module for Python
Python
16
star
18

gerrit-debian

Gerrit package for Debian
Shell
16
star
19

ksm-init.d-debian

init.d script for KVM KSM on Debian GNU/Linux
Shell
15
star
20

cl-skeleton

My personal project template for Common Lisp
Shell
14
star
21

rust-sshkeys

Rust library for reading OpenSSH public keys and certificates
Rust
14
star
22

cl-wol

Wake on LAN (WoL) system for Common Lisp
Common Lisp
13
star
23

rust-zbx

Rust crate for creating Zabbix loadable modules
Rust
11
star
24

cl-rfc4251

Common Lisp library for encoding and decoding RFC 4251 compliant data
Common Lisp
11
star
25

cl-bcrypt

Common Lisp system for parsing and generating bcrypt password hashes
Common Lisp
11
star
26

py-freebsd

Python interface to FreeBSD-specific system libraries
C
9
star
27

py-vevents

VMware vSphere Events from the command-line
Python
8
star
28

go-ucs

Go library for the Cisco UCS Manager API
Go
8
star
29

git-helpers

Git helpers for change deployment
Shell
5
star
30

gerrit-freebsd

FreeBSD Port for Gerrit
5
star
31

openstack-cfengine-ubuntu

OpenStack Cfengine Configurations for Ubuntu
4
star
32

create-ticket

Script to log a ticket in Atlassian Jira instance
Perl
4
star
33

go-chucknorris

Go API and CLI tool for the hand curated Chuck Norris facts.
Go
4
star
34

py-ssh-chroot

A Python script which automates the creation of SSH chroots
Python
4
star
35

go-uuid-endianness

Convert Big Endian UUID to Middle Endian
Go
3
star
36

go-deque

A simple, generic and thread-safe deque implementation
Go
3
star
37

pylobby

Distributed chat system
Python
3
star
38

cfengine3-handbook

Example configuration files for Cfengine3
Shell
3
star
39

shell-template

Template shell script files
Shell
2
star
40

go-traceroute

Implementation of the traditional, ancient method of tracerouting, which uses probes as UDP datagram packets and an unlikely destination port
Go
2
star
41

kubernetes-periodic-controller

An example of a periodic Kubernetes controller
Go
2
star
42

go-graph

Simple and generic graph library
Go
2
star
43

mod_xml2enc

FreeBSD Port for www/mod_xml2enc
1
star
44

proxmoxve-cfengine-debian

Proxmox VE Cfengine configurations for Debian
1
star
45

wargames.unix-heaven.org

The UNIX/Linux Wargames Project Code
Shell
1
star
46

go-utils

A collection of various Go utility packages
Go
1
star
47

jenkins-freebsd

Jenkins port for FreeBSD
1
star
48

dotfiles

dotfiles
Shell
1
star
49

mail-dxs

Simple Mail Data Xchange Service
Shell
1
star
50

awesome-go

A curated list of awesome Go frameworks, libraries and software
Go
1
star
51

cert-manager-webhook-bind9

ACME DNS-01 Solver for Cert Manager using BIND as the DNS provider
Go
1
star
52

php-cms-site-old

Playing with PHP in a time long, long ago...
PHP
1
star
53

pkg_add_it

FreeBSD Port for ports-mgmt/pkg_add_it
1
star
54

py-pkg

Python wrappers for libpkg
Python
1
star
55

check_backlog

Nagios plugin for checking backlog in a folder
1
star
56

wa-admin

Tool for managing Webalizer Apache vhosts
1
star
57

check_mounts

Nagios plugin for checking missing mounts on Linux vservers
1
star
58

dns-zone-checker

A shell script to verify your DNS zones
Shell
1
star