Convenience Golang module enabling you to run embedded Minio server for purpose of integration testing of AWS S3 operations.
There is an open feature request on the Minio GitHub project. It describes the necessary steps to use Minio in your tests, but still there is no easily (re-)useable code for that purpose.
Notably, following features would we very useful:
- Do no hard-code the port to which Minio server will bind, instead use a free port determined at run time
- Create a bucket after starting the server
- Provide a tear-down function that will shut down the Minio server after the test is done
- Clean up files created by the test after the test is done
All of those features are provided by this module.
- Golang 1.15: uses Golang's test TempDir feature
$ go get github.com/draganm/miniotest
this project's test demonstrates the use of the embedded Minio for testing.
UPDATE it turns out that starting/stopping/starting Minio sever in this way does not work. This is because there are quite a few global states and signal handlers being installed and not cleaned up.
Because of this, one can start the embedded server only once per test process and use test Main() method to set up / tear down the embedded server.
On the up side, one can create one bucket per test, so there won't be any interferences between tests, unless one tests creation of buckets.
func Test1(t *testing.T) {
mc, err := mclient.New(addr, &mclient.Options{
Creds: credentials.NewStaticV4("minioadmin", "minioadmin", ""),
Secure: false,
})
require.NoError(t, err)
data := []byte("test")
_, err = mc.PutObject(context.Background(), "test", "foo/var", bytes.NewReader(data), int64(len(data)), mclient.PutObjectOptions{})
require.NoError(t, err)
}
func Test2(t *testing.T) {
mc, err := mclient.New(addr, &mclient.Options{
Creds: credentials.NewStaticV4("minioadmin", "minioadmin", ""),
Secure: false,
})
require.NoError(t, err)
data := []byte("test")
_, err = mc.PutObject(context.Background(), "test", "foo/var", bytes.NewReader(data), int64(len(data)), mclient.PutObjectOptions{})
require.NoError(t, err)
}
var addr string
func TestMain(m *testing.M) {
var cleanup func() error
var err error
addr, cleanup, err = miniotest.StartEmbedded()
if err != nil {
fmt.Fprintf(os.Stderr, "while starting embedded server: %s", err)
os.Exit(1)
}
exitCode := m.Run()
err = cleanup()
if err != nil {
fmt.Fprintf(os.Stderr, "while stopping embedded server: %s", err)
}
os.Exit(exitCode)
}
Function miniotest.StartEmbedded()
starts Minio server and returns a string representing bound address:port
where Minio is listening.
You can use this address as the endpoint for your S3 client (e.g. minio client).
Second value returned is a function that will shut down the started Minio server when called. The best use of this function is to be deferred until the test function returns (as shown in the example).
Miniotest will force embedded Minio server to bind to localhost
and a free port.
Free port is determined by opening a TCP listener with the port 0
, getting the bound port and closing the listener.
hostname:port
bind address will be returned as the first return value of miniotest.StartEmbedded()
Note: there is a possible race condition with this approach, which can lead to Minio server not starting if some other process binds the same port between closing the listener and starting the Minio server. Window of opportunity for this to happen is very short and one can assume this won't happen in 99.999% of cases.
When not specified otherwise, Minio will assume that both accessKeyID
and secretAccessKey
are set to minioadmin
and you should be using this for your tests.
Please do not set environment variables MINIO_ACCESS_KEY
and MINIO_SECRET_KEY
because this will break the setup code for the embedded Minio server.
Miniotest will create bucket named test
as a convenience for the tests run.
Embedded Minio server won't be listening for TLS connections, hence one should not use the S3 client with this option enabled. If someone really needs this feature, please raise an issue on this project, or even better offer a pull request for it.
Contributions are welcome, send your issues and PRs to this repo.
MIT - Copyright Dragan Milic and contributors