Kotlin pure Mockito integration testing with jacoco and SQLite

Submitted by Dickens A S on Mon, 05/08/2023 - 06:16

This article demonstrate an unique technique of doing integration testing using

ReflectionTestUtils.setField

For a difference the code written on top of SQLite instead of H2

usage of ReflectionTestUtils

@BeforeEach
fun setup() {
	MockitoAnnotations.openMocks(this)
	service = NLayerServiceImplTest()
	service?.setup()
	
	ReflectionTestUtils.setField(controller!!, "service", service)

	this.mockMvc =  MockMvcBuilders.standaloneSetup(controller).build();
}

As per the above code NLayerServiceImplTest also has similar setup() method. The NLayerServiceImplTest implements the service interface

code of NLayerServiceImplTest

class NLayerServiceImplTest: NLayerService {

    private var dao:NLayerDAOImplTest? = null
	
    @InjectMocks
    private var service:NLayerServiceImpl? = null

    fun setup() {
		MockitoAnnotations.openMocks(this);
        dao = NLayerDAOImplTest()
        dao?.setup()
		
		ReflectionTestUtils.setField(service!!, "dao", dao)
    }

    override fun findAll(): List<EmployeeVO?>? {
        return service?.findAll()
    }
}

This type of code enables the developer to inject the next layer and implement the method override fun findAll

Where is the testing is happening ?

@Test
fun findAll() {
	var result:MvcResult? = mockMvc?.perform(MockMvcRequestBuilders.get("/demo"))
		?.andExpect(MockMvcResultMatchers.status().isOk())
		?.andReturn();

	val content: String? = result?.getResponse()?.getContentAsString()
	println(content)
}

Only at the controller test class  NLayerControllerTest the above test method is written, so all other layers will be automatically called in real time and all the functionality will be covered in one test method

Where is the Database ?

class NLayerDAOImplTest: NLayerDAO {
    @Mock
    var entityManager: EntityManager? = null

    @Mock
    var typedQuery: TypedQuery<EmployeeVO>? = null

    @InjectMocks
    var dao: NLayerDAOImpl? = null

    fun setup() {
        MockitoAnnotations.openMocks(this)
        val lst = ArrayList<EmployeeVO>()

        val x = EmployeeVO()
        x.id = 1
        x.name = "ram"
        x.salary = 10000
        lst.add(x)

        `when`(typedQuery?.getResultList()).thenReturn(lst)
        `when`(entityManager?.createQuery("select e from EmployeeVO e", EmployeeVO::class.java)).thenReturn(typedQuery)
		
		ReflectionTestUtils.setField(dao!!, "entityManager", entityManager)
    }

    override fun findAll(): List<EmployeeVO?>? {
        return dao?.findAll()
    }

}

Here the EntityManager itself is mocked and therefore the outcome of SQL query "select e from EmployeeVO e" returns a manually created ArrayList

So all part of the source code is invoked due to the fact all layers are chain mocked and injected.

Jacoco report 70% coverage

Jacoco report 70% coverage

GitHub Source code

That's All :)

Comments

Add new comment