Part 4: Writing Tests
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.