Testing code that talks to the network, APIs, databases, external services, is where a lot of test-writing time quietly disappears. The logic you actually want to check is simple, but standing up realistic responses for every dependency is not. This post walks through why that happens and how a Go mocks and stubs generator that records real calls can take most of that work off your plate.
Testing network stuff like APIs and database calls can be a real pain:
- I find myself burning way too much time just making mock data, instead of actually doing the tests or assertions.
- When you make fake mocks, you might end up using wrong guesses or data that is just too unreal or vague.
- When things (the contract) change, you have to dig around and update everything by hand. It is a bit of a headache.
The Search for a Better Way to Mock Dependencies
I was searching for a more efficient way to imitate HTTP dependencies. I found a great library on Google’s GitHub page, at github.com/google/go-replayers. It piqued my interest because it let me record my HTTP dependencies, and hey, it is working out for Google, right?
Still, it was not all smooth sailing. A couple of issues popped up:
- Reading and editing the recorded stubs was difficult. Scrubbing sensitive information such as personal details and keys was especially challenging, particularly when recording from live production sources.
- Keeping these stubs fresh was a DIY job, with API developers rarely giving the API mocks a second glance. So there was always a risk of slipping into wrong assumptions.
Wouldn’t it be awesome to make believable, easy-to-understand mocks or stubs that can double as API test cases?
What Keploy’s Go Mocks and Stubs Generator Does
So we got down to coding and built our own Go mocks and stubs generator library in Keploy to help with TDD workflows. This tool has a unique capability: it can create tests and mocks from real API or database calls. In contrast, gomock only creates types that you then have to fill in by hand.
It helps to be clear on the terms. A stub returns a canned, predefined response when your code calls a dependency, so the code under test has something realistic to work with. A mock does that too, but also lets you assert how the dependency was called. The problem with writing either by hand is that the data is invented, so it drifts from reality over time. Keploy sidesteps that by recording the actual responses your dependencies return, then replaying them, so your stubs stay lifelike because they came from real traffic in the first place.
The best part? You can use API call tests as Go mocks and stubs, and vice versa.

Setting Up the Example
Let’s roll up our sleeves and dive into a unit-testing example I found on a nifty blog. We will be swapping out the handcrafted mocking behaviour with lifelike recorded stubs. First, let’s get our directory structure in shape:
You can swipe the starting code from these GitHub gists: example.go and example_test.go.
Installing Keploy
First things first, we need to download and fire up keploy.
Mac
Linux
That should download and kick-start the keploy server. You should see something like this:
Wrapping the HTTP Client
Now that the Keploy server is humming along, we can bring in the Keploy Go SDK and start building our mocks and stubs. Keploy needs all network clients (like HTTP clients or DB drivers) to be wrapped so it can intercept the calls flowing through them. That interception is the whole trick: once a client is wrapped, Keploy sees every request and response and can record or replay it. So here, we wrap the HTTP client with Keploy’s net/http wrapper.
Recording Your Stubs
With the client wrapped, we start the Keploy SDK and put it in record mode. In this mode Keploy watches the real calls your test makes and captures the responses as reusable stubs.
Like most profiling tools in Golang, Keploy needs you to pass the context.Context object to all the dependencies. The SDK uses this context to keep all the different parts of your app in sync, which is what lets it match a recorded response back to the right call. Ready to record our stubs with go test?
Voila. The orange lines are Keploy confirming it captured the outputs of each HTTP dependency call. Our stubs are ready to roll. By default they are created in the mocks folder, but you can easily customize this.
Switching to Test Mode
After the stubs are created, we switch the mode in the Keploy object from record to test. Now, instead of hitting the real dependency, Keploy serves the responses it recorded earlier.
With that out of the way, we can rerun our tests:
Magic, isn’t it? This time the clown-face lines show Keploy returning the previously recorded stub responses instead of making a live call, which is why the test runs the same way every time with no real dependency in the loop. You can find the complete code for this blog here.
Beyond HTTP: Other Dependencies
You can make realistic stubs (service virtualization) for any dependency supported by Keploy. This includes Postgres, MySQL, gRPC client and server, and more. All you need to do is follow the same steps: wrap the client, record once, then replay in test mode. The same recorded interactions can double as API testing cases, so you are not maintaining two separate sets of fixtures. Don’t hesitate to give it a shot and share your experience on the Keploy Slack channel.
Frequently Asked Questions
What is the difference between a mock and a stub?
A stub provides canned responses to calls made during a test, giving your code realistic data to work with. A mock does the same but also lets you verify how the dependency was called. Keploy blurs the line usefully: it records real dependency responses and replays them, so you get lifelike stubs and reusable test cases from the same capture.
How is Keploy different from gomock?
gomock generates mock types from interfaces, which you then wire up and populate with expected values by hand. Keploy instead records real API and database calls and generates the stubs, mocks, and test cases automatically from that real traffic, so you are not inventing the data yourself.
Which dependencies can Keploy mock?
Keploy can create stubs for a range of dependencies, including HTTP clients, Postgres, MySQL, and gRPC client and server calls, among others. The workflow is the same for each: wrap the client so Keploy can intercept it, record once, then replay.
Do I need to change my application code to use Keploy?
You do not rewrite your logic, but you do wrap your network clients so Keploy can intercept them, for example wrapping the HTTP client with the khttpclient interceptor, and pass context.Context through to your dependencies. After that, recording and replaying is just a matter of switching the mode between record and test.
What’s Next
We are also excited about upcoming work that uses generative AI to write test code that actually works, rather than the half-baked, semi-working tests produced by most GPT-based test generators. The goal is the same one that motivated this library in the first place: spend less time hand-crafting mocks and more time on the tests that matter.

