The way that Go-Lang handles unit testing requires that you define a function that takes the testing.T as a function argument.

  1. Why I like Go-Lang
  2. Why I like Go-ORM
  3. Why I like Go-Fiber
  4. Go-Fiber: Request Validation
  5. Go-Lang: JSON Web Tokens
  6. Go-Lang: Unit Testing (You’re here)
  7. Go-Fiber: Dependency Injection

Go-routines are an effective tool in this situation. You can start a go-routine to handle requests while the primary routine performs the testing.

Let’s import the necessary package; with several variables which will be needed with the testing.

import (
...
"testing"
...
)
const (
port = ":3000"
address = "http://localhost" + port
testemail = "testing@email.com"
goodpassword = "nice_12345"
badpassword = "never_share_encourage_regression_to_the_mean"
)

Three pieces of functionality are going to be tested;

  1. Registration works
  2. Login with the right password allows access
  3. Login with the wrong password denies access.
func PersonTesting(t *testing.T) {
db = database.connect(...)
defer db.Close()
personAPI := PersonAPI()
go personAPI.Listen(port)
client := &http.Client{}
...

Multiple requests are going to be sent and the parameter is needed to use the testing library, lambdas are utilized to keep the scope of the original function.

  ...
performGoodRequest := func(message []byte, reqType string)[]byte {
req, err := http.NewRequest(reqType, url, message))
if err != nil {
t.Error(err)
}
req.Header.Add("Content-Type", "application/json")
res, err := client.Do(req)
if err != nil {
t.Error(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
t.Error(err)
}
return body
}
performBadRequest := func(message []byte, reqType string) {
req, err := http.NewRequest(reqType, url, message))
if err != nil {
t.Error(err)
}
req.Header.Add("Content-Type", "application/json")
res, err := client.Do(req)
defer res.Body.Close()
if err == nil {
t.Error("Worked when it shouldn't have.")
}
}
...

Okay; the lambdas defined. Let’s register a new person. Initialize the struct; parse it into a json message.

  ...
per := Person{testemail, goodpassword}
body, err := json.Marshal(per)
if err != nil {
t.Error(err)
}
...

The first test is to register the new person.

  ...
body = performGoodRequest(body, "POST")
var rper Person
err = json.Unmarshal(body, &rper)
if err != nil {
t.Error(err)
}
if rper.Email != per.Email {
t.Error("emails do not match")
}
...

Okay, now the log in attempt with a bad password.

  ...
badper := Person{testemail, badpassword}
body, err := json.Marshal(badper)
if err != nil {
t.Error(err)
}
performBadRequest(body, "GET")
...

Okay, now the log in attempt with a good password.

  ...
goodPer:= Person{testemail, goodpassword}
body, err := json.Marshal(goodper)
if err != nil {
t.Error(err)
}
body = performGoodRequest(body, "GET")
var resPer Person
err = json.Unmarshal(body, &resPer)
if err != nil {
t.Error(err)
}
if resPer.Email != rper.Email{
t.Error(err)
}
...

Now reset the state back to the way it was before the function was called. A word for this exists, do you know what it is?

  ...  
db.Delete(&per)
}

This function will check the features that the API provides are functioning within specifications. How would you do it differently?

awake, software engineer.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store