Part 4: Writing Tests

Erwin Alberto
3 min readJan 22, 2018

--

To build quality code, we must always write tests for it. In this application, I wrote tests for the service, controller and DAO classes. I used JUnit to do this. With the help of spring-boot-starter-test, I was able to easily use the Spring Boot test modules as well as JUnit.

package com.erwindev.openpayment.dao

import com.erwindev.openpayment.domain.OpenPayment
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.TestPropertySource
import org.springframework.test.context.junit4.SpringRunner

/**
* Created by erwinalberto on 1/6/18.
*/
@RunWith(SpringRunner::class)
@SpringBootTest
@TestPropertySource(locations=arrayOf("classpath:application-test.properties"))
class OpenPaymentDaoTest {

@Autowired
lateinit var openPaymentDao: OpenPaymentDao

@Test
fun testCreateOpenPayment(){
var openPayment: OpenPayment =
OpenPayment(providerId = "1234",
providerName = "Dr. Jack",
paymentAmount = 94.30,
payerId = "12399393",
payerName = "Walgreens")

openPaymentDao.insert(openPayment)

var savedOpenPayment = openPaymentDao.findById(1)

assertEquals(openPayment.id, savedOpenPayment.id)
}

}

A few things to note here.

  • @RunWith annotation provides a bridge between Spring Boot test features and JUnit. This annotation is required every time JUnit is used.
  • @SpringBootTest annotation bootstraps the entire container. It tells the test application to look for the main class defined by @SpringBootApplication. It uses that class to start a Spring application context.
  • @TestPropertySource annotation tells the test application to use a different property file for running the test application. In this case, I am using application-test.properties.
  • @Test annotation tells the test application which functions to test.
  • I am also injecting the OpenPaymentDao object. I am using that object to save data in the database. Then, I query that object back and perform an assertEquals to compare the object that I saved to the object that I queried.

The web layer tests adds some more nuances when testing the REST endpoints.

package com.erwindev.openpayment.controller

import com.erwindev.openpayment.domain.OpenPayment
import com.erwindev.openpayment.service.OpenPaymentService
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.TestPropertySource
import org.springframework.test.context.junit4.SpringRunner
import org.springframework.test.context.web.WebAppConfiguration
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.web.context.WebApplicationContext
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status


/**
* Created by erwinalberto on 1/6/18.
*/
@RunWith(SpringRunner::class)
@SpringBootTest
@WebAppConfiguration
@TestPropertySource(locations=arrayOf("classpath:application-test.properties"))
class WebLayerTest {
private var mvc:MockMvc? = null

@Autowired
lateinit var context: WebApplicationContext

@Autowired
lateinit var openPaymentService : OpenPaymentService

@Before
fun setup(){
mvc = MockMvcBuilders.webAppContextSetup(context).build()

var openPayment: OpenPayment =
OpenPayment(id=1,
providerId = "1234",
providerName = "Dr. Jack",
paymentAmount = 94.30,
payerId = "12399393",
payerName = "Walgreens")

openPaymentService.addOpenPayment(openPayment)

}

@Test
fun testGetPayments(){
val result = mvc?.perform(get("/api/openpayment/v1/payments"))?.andExpect(status().isOk)?.andReturn()

val content : String? = result?.response?.contentAsString

val gson = Gson()

val openPayments : List<OpenPayment> = gson.fromJson(content, object : TypeToken<List<OpenPayment>>() {}.type)

assertEquals(openPayments[0].id, "1".toLong())

}
}

Some things I had to consider when testing a REST Controller.

  • Since I am testing a class that handles HTTP requests, I had to inject the WebApplicationContext. This will allow me to create a MockMvc object which will in turn allow me to perform test GET HTTP calls to my REST endpoints.
  • @Before annotation ensures that the function is executed prior to running the test methods. In this case, I wanted to insert the payment data to a database before I retrieve the contents of it. Additionally, the contents returned by the REST service will be converted to a list of OpenPayment object so I can easily compare the result.

In the next and final part of this tutorial, I will show you how to run the application.

Part 5: Let’s take the application for a spin

You can find the code this GitHub repo.

--

--