Carrying out integration tests for APIs means that we must at least be able to run the application first so that integrated testing can be carried out.
We need to prepare several cases, test cases that cover the needs of the integration test. For example, the API Endpoint' that we have worked on has a
database,
cache` or other external resource that is related to the continuity of the API Endpoint.
So, we will simulate how to carry out an API integration test. The first stage is that we create an API Service where the API is used for number addition operations.
Create API Programs
The following is the API Endpoint program that will be tested or an integration test will be created.
package main
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
)
func main() {
http.HandleFunc("/add", HandleAddInts)
address := ":9000"
fmt.Printf("Memulai server at %s\n", address)
fmt.Println()
fmt.Println("contoh query: /add?a=2&b=2&authtoken=abcdef123")
fmt.Println("tokennya adalah 'abcdef123'")
err := http.ListenAndServe(address, nil)
if err != nil {
fmt.Printf("error ketika start server: %v", err)
}
}
type TambahResponse struct {
Result int `json:"result"`
}
func HandleAddInts(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()
paramA := params.Get("a")
paramB := params.Get("b")
token := params.Get("authtoken")
if paramA == "" || paramB == "" || token == "" {
http.Error(w, "tidak ada parameters", http.StatusBadRequest)
return
}
if token != "abcdef123" {
http.Error(w, "token tidak valid", http.StatusUnauthorized)
return
}
intA, err := strconv.Atoi(paramA)
if err != nil {
http.Error(w, "parameter 'a' harus integer", http.StatusBadRequest)
return
}
intB, err := strconv.Atoi(paramB)
if err != nil {
http.Error(w, "parameter 'b' harus integer", http.StatusBadRequest)
return
}
response := TambahResponse{
Result: intA + intB,
}
json, err := json.MarshalIndent(&response, "", " ")
if err != nil {
http.Error(w, "error while marshalling", http.StatusInternalServerError)
return
}
fmt.Fprint(w, string(json))
}
In this program there are several validations when the program is run, namely * The parameters entered must be integer
- Do not fill in the parameters
a
andb
then it will become - Test if it doesn’t send
authToken
After the above program is complete, we run it with the command
➜ integration-test git:(main) ✗ go run app/main.go
Memulai server at :9000
contoh query: /add?a=2&b=2&authtoken=abcdef123
tokennya adalah 'abcdef123'
If the program has run successfully, it will be visible or can be accessed using postman and curl
with endpoint and port :9000
.
➜ materi curl 'http://localhost:9000/add?a=2&b=2&authtoken=abcdef123'
{
"result": 4
}%
If the program is successful as above then, we have run the API program to add numbers using the http
protocol.
Create Integration Tests
Next, we will create an API integration test that we created earlier with several cases mentioned above.
Prepare the program or file main.go
to create API Testing.
package integrationtest
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type MathClient struct {
Token string
Host string
}
type AddResult struct {
Result int `json:"result"`
}
func (c *MathClient) APISum(i, j int) (int, error) {
query := fmt.Sprintf("http://%s/add?a=%v&b=%v&authtoken=%v", c.Host, i, j, c.Token)
response, err := http.Get(query)
if err != nil {
return 0, err
}
defer response.Body.Close()
data, err := ioutil.ReadAll(response.Body)
if err != nil {
return 0, err
}
a := AddResult{}
err = json.Unmarshal(data, &a)
if err != nil {
return 0, err
}
return a.Result, nil
}
We will use the APISum
method to access the http
API that we have created as the main server which we will test using this integration test.
Create Client Struct
Create a struct for the API structure and response like this.
type MathClient struct {
Token string
Host string
}
type AddResult struct {
Result int `json:"result"`
}
Create a Sum API Access Method
then we will create a method to retrieve the API sum data.
func (c *MathClient) APISum(i, j string) (int, int, error) {
query := fmt.Sprintf("http://%s/add?a=%s&b=%s&authtoken=%v", c.Host, i, j, c.Token)
var statusCode int = http.StatusBadRequest
response, err := http.Get(query)
if err != nil {
return 0, statusCode, err
}
defer response.Body.Close()
statusCode = response.StatusCode
data, err := ioutil.ReadAll(response.Body)
if err != nil {
return 0, statusCode, err
}
a := AddResult{}
err = json.Unmarshal(data, &a)
if err != nil {
return 0, statusCode, err
}
return a.Result, statusCode, nil
}
Create a Unit Test which is used as an Integration Test
Next, we will create this API Integration testing in this method. We can make a program like this or just generate
in the APISum
method.
func TestMathClient_APISum(t *testing.T) {
type fields struct {
Token string
Host string
}
type args struct {
i string
j string
}
tests := []struct {
name string
fields fields
args args
want int
wantErr bool
wantCode int
}{
// testing test case
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &MathClient{
Token: tt.fields.Token,
Host: tt.fields.Host,
}
got, gotCode, err := c.APISum(tt.args.i, tt.args.j)
if (err != nil) != tt.wantErr {
t.Errorf("MathClient.APISum() error = %v, wantErr %v", err, tt.wantErr)
return
}
if got != tt.want {
t.Errorf("MathClient.APISum() = %v, want %v", gotCode, tt.wantCode)
}
if gotCode != tt.wantCode {
t.Errorf("MathClient.APISum() = %v, want %v", gotCode, tt.wantCode)
}
})
}
}
Add Test Cases
Then, so that we can carry out case by case
testing, we need to fill in the number of cases in the curly brackets above with contents like this.
{
name: "case sukses jumlah data",
fields: fields{
Token: "abcdef123",
Host: "localhost:9000",
},
args: args{
i: "2",
j: "2",
},
want: 4,
wantErr: false,
wantCode: http.StatusOK,
},
{
name: "token tidak diset",
fields: fields{
Token: "abc",
Host: "localhost:9000",
},
args: args{
i: "2",
j: "2",
},
want: 0,
wantErr: true,
wantCode: http.StatusUnauthorized,
},
{
name: "host tidak sesuai",
fields: fields{
Token: "abcdef123",
Host: "localhost:500",
},
args: args{
i: "2",
j: "2",
},
want: 0,
wantErr: true,
wantCode: http.StatusBadRequest,
},
{
name: "case parameter kosong",
fields: fields{
Token: "abcdef123",
Host: "localhost:9000",
},
args: args{
i: "",
j: "",
},
want: 0,
wantErr: true,
wantCode: http.StatusBadRequest,
},
{
name: "case parameter bukan integer",
fields: fields{
Token: "abcdef123",
Host: "localhost:9000",
},
args: args{
i: "a",
j: "a",
},
want: 0,
wantErr: true,
wantCode: http.StatusBadRequest,
},
Run Integration Test
Everything has been completed for testing and creating tests. Don’t forget that because this is integration test
code, we need to add something so that when we do go test -v
we can add the code above like this.
//go:build integration
We continue by running go test with the integration
parameter
$ go test -v -tags=integration
Also make sure the API Endpoint program is running
➜ integration-test git:(main) ✗ go run app/main.go
Memulai server at :9000
contoh query: /add?a=2&b=2&authtoken=abcdef123
tokennya adalah 'abcdef123'