implement some ad-hoc mocks for responses

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2025-10-25 01:36:38 +02:00
parent 056e314645
commit 4afbd6146b
7 changed files with 48 additions and 21 deletions

View File

@ -3,6 +3,7 @@ package image
import (
"context"
"io"
"net/http"
"strings"
"time"
@ -28,6 +29,14 @@ type fakeClient struct {
imageBuildFunc func(context.Context, io.Reader, client.ImageBuildOptions) (client.ImageBuildResult, error)
}
type fakeStreamResult struct {
io.ReadCloser
client.ImagePushResponse // same interface as [client.ImagePullResponse]
}
func (e fakeStreamResult) Read(p []byte) (int, error) { return e.ReadCloser.Read(p) }
func (e fakeStreamResult) Close() error { return e.ReadCloser.Close() }
func (cli *fakeClient) ImageTag(_ context.Context, options client.ImageTagOptions) (client.ImageTagResult, error) {
if cli.imageTagFunc != nil {
return cli.imageTagFunc(options)
@ -54,7 +63,7 @@ func (cli *fakeClient) ImagePush(_ context.Context, ref string, options client.I
return cli.imagePushFunc(ref, options)
}
// FIXME(thaJeztah): how to mock this?
return nil, nil
return fakeStreamResult{ReadCloser: http.NoBody}, nil
}
func (cli *fakeClient) Info(_ context.Context) (system.Info, error) {
@ -69,7 +78,7 @@ func (cli *fakeClient) ImagePull(_ context.Context, ref string, options client.I
return cli.imagePullFunc(ref, options)
}
// FIXME(thaJeztah): how to mock this?
return nil, nil
return fakeStreamResult{ReadCloser: http.NoBody}, nil
}
func (cli *fakeClient) ImagesPrune(_ context.Context, opts client.ImagePruneOptions) (client.ImagePruneResult, error) {

View File

@ -4,7 +4,10 @@ import (
"errors"
"fmt"
"io"
"reflect"
"strings"
"testing"
"unsafe"
"github.com/docker/cli/internal/test"
"github.com/moby/moby/client"
@ -71,8 +74,18 @@ func TestNewLoadCommandInvalidInput(t *testing.T) {
assert.ErrorContains(t, err, expectedError)
}
func mockImageLoadResult(content string, json bool) client.ImageLoadResult {
out := client.ImageLoadResult{JSON: json}
// Set unexported field "body"
v := reflect.ValueOf(&out).Elem()
f := v.FieldByName("body")
r := io.NopCloser(strings.NewReader(content))
reflect.NewAt(f.Type(), unsafe.Pointer(f.UnsafeAddr())).Elem().Set(reflect.ValueOf(r))
return out
}
func TestNewLoadCommandSuccess(t *testing.T) {
t.Skip("FIXME(thaJeztah): how to mock this?")
testCases := []struct {
name string
args []string
@ -84,7 +97,7 @@ func TestNewLoadCommandSuccess(t *testing.T) {
imageLoadFunc: func(input io.Reader, options ...client.ImageLoadOption) (client.ImageLoadResult, error) {
// FIXME(thaJeztah): how to mock this?
// return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil
return client.ImageLoadResult{}, nil
return mockImageLoadResult(`Success`, false), nil
},
},
{
@ -92,12 +105,11 @@ func TestNewLoadCommandSuccess(t *testing.T) {
args: []string{},
imageLoadFunc: func(input io.Reader, options ...client.ImageLoadOption) (client.ImageLoadResult, error) {
// FIXME(thaJeztah): how to mock this?
// return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil
// return client.ImageLoadResult{
// Body: io.NopCloser(strings.NewReader(`{"ID": "1"}`)),
// JSON: true,
// }, nil
return client.ImageLoadResult{JSON: true}, nil
return mockImageLoadResult(`{"ID":"1"}`, true), nil
},
},
{
@ -106,7 +118,7 @@ func TestNewLoadCommandSuccess(t *testing.T) {
imageLoadFunc: func(input io.Reader, options ...client.ImageLoadOption) (client.ImageLoadResult, error) {
// FIXME(thaJeztah): how to mock this?
// return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil
return client.ImageLoadResult{}, nil
return mockImageLoadResult(`Success`, false), nil
},
},
{
@ -118,7 +130,7 @@ func TestNewLoadCommandSuccess(t *testing.T) {
// assert.Check(t, is.Contains(options, client.ImageHistoryWithPlatform(ocispec.Platform{OS: "linux", Architecture: "amd64"})))
// FIXME(thaJeztah): how to mock this?
// return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil
return client.ImageLoadResult{}, nil
return mockImageLoadResult(`Success`, false), nil
},
},
{
@ -128,7 +140,7 @@ func TestNewLoadCommandSuccess(t *testing.T) {
assert.Check(t, len(options) > 0) // can be 1 or two depending on whether a terminal is attached :/
// FIXME(thaJeztah): how to mock this?
// return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil
return client.ImageLoadResult{}, nil
return mockImageLoadResult(`Success`, false), nil
},
},
{
@ -138,7 +150,7 @@ func TestNewLoadCommandSuccess(t *testing.T) {
assert.Check(t, len(options) > 0) // can be 1 or two depending on whether a terminal is attached :/
// FIXME(thaJeztah): how to mock this?
// return client.ImageLoadResult{Body: io.NopCloser(strings.NewReader("Success"))}, nil
return client.ImageLoadResult{}, nil
return mockImageLoadResult(`Success`, false), nil
},
},
}

View File

@ -1,9 +1,9 @@
package image
import (
"errors"
"fmt"
"io"
"net/http"
"testing"
"github.com/docker/cli/internal/test"
@ -49,7 +49,6 @@ func TestNewPullCommandErrors(t *testing.T) {
}
func TestNewPullCommandSuccess(t *testing.T) {
t.Skip("FIXME(thaJeztah): how to mock this?")
testCases := []struct {
name string
args []string
@ -77,7 +76,7 @@ func TestNewPullCommandSuccess(t *testing.T) {
imagePullFunc: func(ref string, options client.ImagePullOptions) (client.ImagePullResponse, error) {
assert.Check(t, is.Equal(tc.expectedTag, ref), tc.name)
// FIXME(thaJeztah): how to mock this?
return nil, nil
return fakeStreamResult{ReadCloser: http.NoBody}, nil
},
})
cmd := newPullCommand(cli)
@ -123,7 +122,7 @@ func TestNewPullCommandWithContentTrustErrors(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
imagePullFunc: func(ref string, options client.ImagePullOptions) (client.ImagePullResponse, error) {
// FIXME(thaJeztah): how to mock this?
return nil, errors.New("shouldn't try to pull image")
return fakeStreamResult{ReadCloser: http.NoBody}, nil
},
})
cli.SetNotaryClient(tc.notaryFunc)

View File

@ -3,6 +3,7 @@ package image
import (
"errors"
"io"
"net/http"
"testing"
"github.com/docker/cli/internal/test"
@ -49,7 +50,6 @@ func TestNewPushCommandErrors(t *testing.T) {
}
func TestNewPushCommandSuccess(t *testing.T) {
t.Skip("FIXME(thaJeztah): how to mock this?")
testCases := []struct {
name string
args []string
@ -72,7 +72,7 @@ func TestNewPushCommandSuccess(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
imagePushFunc: func(ref string, options client.ImagePushOptions) (client.ImagePushResponse, error) {
// FIXME(thaJeztah): how to mock this?
return nil, nil
return fakeStreamResult{ReadCloser: http.NoBody}, nil
},
})
cmd := newPushCommand(cli)

View File

@ -3,7 +3,7 @@ package plugin
import (
"context"
"io"
"strings"
"net/http"
"github.com/moby/moby/api/types/system"
"github.com/moby/moby/client"
@ -79,5 +79,5 @@ func (c *fakeClient) PluginUpgrade(_ context.Context, name string, options clien
return c.pluginUpgradeFunc(name, options)
}
// FIXME(thaJeztah): how to mock this?
return io.NopCloser(strings.NewReader("")), nil
return http.NoBody, nil
}

View File

@ -4,8 +4,8 @@ import (
"bytes"
"context"
"encoding/hex"
"errors"
"io"
"net/http"
"testing"
"github.com/docker/cli/cli/trust"
@ -27,6 +27,14 @@ type fakeClient struct {
client.Client
}
type fakeStreamResult struct {
io.ReadCloser
client.ImagePushResponse // same interface as [client.ImagePullResponse]
}
func (e fakeStreamResult) Read(p []byte) (int, error) { return e.ReadCloser.Read(p) }
func (e fakeStreamResult) Close() error { return e.ReadCloser.Close() }
func (*fakeClient) Info(context.Context) (system.Info, error) {
return system.Info{}, nil
}
@ -37,7 +45,7 @@ func (*fakeClient) ImageInspect(context.Context, string, ...client.ImageInspectO
func (*fakeClient) ImagePush(context.Context, string, client.ImagePushOptions) (client.ImagePushResponse, error) {
// FIXME(thaJeztah): how to mock this?
return nil, errors.New("don't handle response")
return fakeStreamResult{ReadCloser: http.NoBody}, nil
}
func TestTrustInspectPrettyCommandErrors(t *testing.T) {

View File

@ -272,7 +272,6 @@ func TestSignCommandChangeListIsCleanedOnError(t *testing.T) {
}
func TestSignCommandLocalFlag(t *testing.T) {
t.Skip("FIXME(thaJeztah): how to mock this?")
cli := test.NewFakeCli(&fakeClient{})
cli.SetNotaryClient(notaryfake.GetEmptyTargetsNotaryRepository)
cmd := newSignCommand(cli)