Unit Testing with Ginkgo : Part 2

Utkarsh Mani Tripathi
3 min readDec 25, 2019

In the previous blog we learned how to bootstrap the initial unit test code using ginkgo and learned to write unit test of a sum function. In this blog we will learn how to test http handlers using test server provided by ginkgo to mock server’s behaviour and test the handlers.

I have already provided the installation instruction and other initial steps in the previous blog, here i will go through the simple http server and its test code.

package mainimport (
"fmt"
"io/ioutil"
"net/http"
)
func Handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, the end point is :%s!", r.URL.Path[1:])
}
func ReadHandler(w http.ResponseWriter, r *http.Request) {
dat, err := ioutil.ReadFile("data.txt")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "Content in file is...\r\n%s", string(dat))
}
func main() {
http.HandleFunc("/", Handler)
http.HandleFunc("/read", ReadHandler)
http.ListenAndServe(":8080", nil)
}

In the above code i have created two handlers, one to handle requests at / and other is /readpath. So in the test code i will be making get request to url path handled by this server.

package mainimport (
"io/ioutil"
"net/http"
"os"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/ghttp"
)
var _ = Describe("Server", func() {
var server *ghttp.Server
msg := "Hi there, the end point is :"
BeforeEach(func() {
// start a test http server
server = ghttp.NewServer()
})
AfterEach(func() {
server.Close()
})
Context("When get request is sent to empty path", func() {
BeforeEach(func() {
// Add your handler which has to be called for a given path
// If there are multiple redirects append all the handlers
server.AppendHandlers(
Handler,
)
})
It("Returns the empty path", func() {
resp, err := http.Get(server.URL() + "/")
Expect(err).ShouldNot(HaveOccurred())
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
Expect(err).ShouldNot(HaveOccurred())
Expect(string(body)).To(Equal(msg + "!"))
})
})
Context("When get request is sent to hello path", func() {
BeforeEach(func() {
server.AppendHandlers(
Handler,
)
})
It("Returns the empty path", func() {
resp, err := http.Get(server.URL() + "/hello")
Expect(err).ShouldNot(HaveOccurred())
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
Expect(err).ShouldNot(HaveOccurred())
Expect(string(body)).To(Equal(msg + "hello!"))
})
})
Context("When get request is sent to read path but there is no file", func() {
BeforeEach(func() {
server.AppendHandlers(
ReadHandler,
)
})
It("Returns internal server error", func() {
resp, err := http.Get(server.URL() + "/read")
Expect(err).ShouldNot(HaveOccurred())
Expect(resp.StatusCode).Should(Equal(http.StatusInternalServerError))
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
Expect(err).ShouldNot(HaveOccurred())
Expect(string(body)).To(Equal("open data.txt: no such file or directory\n"))
})
})
Context("When get request is sent to read path but file exists", func() {
BeforeEach(func() {
file, err := os.Create("data.txt")
Expect(err).NotTo(HaveOccurred())
file.Write([]byte("Hi there!"))
server.AppendHandlers(
ReadHandler,
)
})
AfterEach(func() {
err := os.Remove("data.txt")
Expect(err).NotTo(HaveOccurred())
})
It("Reads data from file successfully", func() {
resp, err := http.Get(server.URL() + "/read")
Expect(err).ShouldNot(HaveOccurred())
Expect(resp.StatusCode).Should(Equal(http.StatusOK))
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
Expect(err).ShouldNot(HaveOccurred())
Expect(string(body)).To(Equal("Content in file is...\r\nHi there!"))
})
})
})

I have added test cases corresponding to individual get requests sent to this server at various paths.

As you can see, all the 4 test cases are passed successfully. This was very simple example to test your handlers at the server side. I want to keep the contents of this blog short, I will cover how to mock the http server at the client side in the next blog. Feel free to comment if you have found any issue and stay tuned for my next blog.

That’s all folks ! As always thanks for reading. 😊

~ उत्कर्ष_उवाच

--

--