问题
Is there an easy way to mock Hashicorp vault in go tests ?
I created a service in Go that accesses Vault, and would like to create proper testing for it.
I didn't find a simple solution I like (like moto in python). I also tried using a vault in dev mode in docker (take the system test route) but I have trouble writing to it via API. Ideas ?
回答1:
Is there an easy way to mock HashiCorp Vault in Go tests?
Don't. Use the real thing! HashiCorp helpfully provides utility functions for starting a server on the fly1. This makes your tests much more useful, and can often serve as an actionable guide for developers on how to setup local development servers too.
Here is a very basic example. The testing framework is very flexible (which also makes it fairly complicated). Refer to the package documentations for more options, including running multiple servers in HA mode. I found Vault's own test cases very useful when setting up more complicated scenarios.
package main
import (
"net"
"testing"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/vault"
)
func TestVaultStuff(t *testing.T) {
ln, client := createTestVault(t)
defer ln.Close()
// Pass the client to the code under test.
myFunction(client)
}
func createTestVault(t *testing.T) (net.Listener, *api.Client) {
t.Helper()
// Create an in-memory, unsealed core (the "backend", if you will).
core, keyShares, rootToken := vault.TestCoreUnsealed(t)
_ = keyShares
// Start an HTTP server for the core.
ln, addr := http.TestServer(t, core)
// Create a client that talks to the server, initially authenticating with
// the root token.
conf := api.DefaultConfig()
conf.Address = addr
client, err := api.NewClient(conf)
if err != nil {
t.Fatal(err)
}
client.SetToken(rootToken)
// Setup required secrets, policies, etc.
_, err = client.Logical().Write("secret/foo", map[string]interface{}{
"secret": "bar",
})
if err != nil {
t.Fatal(err)
}
return ln, client
}
1 They provide test servers for all of their projects, not just Vault. Mitchell Hashimoto explained the rational in his talk on advanced testing.
回答2:
Because Go is a statically typed language we have to know the type of things at compile time. So to do this type of independent testing we need to create boundaries in our code that make logical sense in terms of testing.
Interfaces are created in Go to define these boundaries, so in this sense you want to create an interface between you and this third party library so that you can replace the inputs and outputs of the libraries functions/methods/types with ones that you can control and have defined conditions so that you can test how your code behaves to outputs or conditions of the third party.
See the below for examples of interfaces.
https://gobyexample.com/interfaces
if you share some example code perhaps we can be a little more specific and give you some code examples.
回答3:
One super important thing to note:
TestCoreUnsealed
doesn't use the regular KV backend, instead it uses a PassthroughBackend
to essentially mock the kv behavior.
follow this issue, i've spent 4 days debugging this
https://github.com/hashicorp/vault/issues/8440
来源:https://stackoverflow.com/questions/57771228/mocking-hashicorp-vault-in-go