I'm trying to test my API endpoint that list files from an AWS S3 Bucket:
func listFiles(w http.ResponseWriter, _ *http.Request) {
client := GetAWSClient()
bucket := aws.String(BUCKETNAME)
input := &s3.ListObjectsV2Input{
Bucket: bucket,
}
resp, err := GetObjects(context.TODO(), client, input)
if err != nil {
...
}
msg, _ := json.Marshal(resp.Contents)
w.WriteHeader(200)
w.Write(msg)
return
}
...
func handleRequest() {
myRouter := mux.NewRouter().StrictSlash(true)
myRouter.HandleFunc("/listFiles", listFiles).Methods("GET")
c := cors.Default()
handler := c.Handler(myRouter)
log.Fatal(http.ListenAndServe(":8080", handler))
}
I see from AWS SDK documentation that to mock AWS client functions you can use it interface so in my main_test.go I created these:
//Testing /listFiles endpoint
type mockListObjectsAPI func(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error)
func (m mockListObjectsAPI) ListObjectsV2(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error) {
return m(ctx, params, optFns...)
}
func TestGetObjectFromS3(t *testing.T) {
cases := []struct {
client func(t *testing.T) S3ListObjectsAPI
bucket string
key string
expect []byte
}{
{
client: func(t *testing.T) S3ListObjectsAPI {
return mockListObjectsAPI(func(ctx context.Context, params *s3.ListObjectsV2Input, optFns ...func(*s3.Options)) (*s3.ListObjectsV2Output, error) {
t.Helper()
if params.Bucket == nil {
t.Fatal("expect bucket to not be nil")
}
if e, a := "fooBucket", *params.Bucket; e != a {
t.Errorf("expect %v, got %v", e, a)
}
return &s3.ListObjectsV2Output{
Name: aws.String("fooBucket"),
}, nil
})
},
bucket: "fooBucket",
key: "barKey",
expect: []byte("this is the body foo bar baz"),
},
//Add more test cases here if needed
}
for i, tt := range cases {
t.Run(strconv.Itoa(i), func(t *testing.T) {
//Here I should compare API returned value with expected in the test cases
})
}
}
My question is, how could I test my API calling it from the test but without calling AWS but instead using the values I mocked?
If I use httptest to call the endpoint it will call the real endpoint calling AWS.