How to write tests for Kotlin projects
This tutorial provides an example of using Diffblue Cover CLI to write Java unit tests for Kotlin projects. We’ll use the Spring PetClinic Kotlin codebase to demonstrate practical applications of Diffblue Cover in a real-world project.
First clone the Spring PetClinic Kotlin project from GitHub and then compile the project ready for use with Cover CLI. Finally, run the Diffblue Cover preflight checks to make sure everything is ready for writing tests:
$ dcover create --preflight
Now let’s write unit tests for a Kotlin class within the codebase. We’ll focus on a simplified version of a controller class (PetController
), responsible for managing pet information:
@Controller
@RequestMapping("/owners/{ownerId}")
class PetController(val pets: PetRepository, val owners: OwnerRepository) {
private val VIEWS_PETS_CREATE_OR_UPDATE_FORM = "pets/createOrUpdatePetForm"
@PostMapping("/pets/new")
fun processCreationForm(owner: Owner, @Valid pet: Pet, result: BindingResult, model: Model): String {
if (StringUtils.hasLength(pet.name) && pet.isNew && owner.getPet(pet.name!!, true) != null) {
result.rejectValue("name", "duplicate", "already exists")
}
owner.addPet(pet)
return if (result.hasErrors()) {
model["pet"] = pet
VIEWS_PETS_CREATE_OR_UPDATE_FORM
} else {
this.pets.save(pet)
"redirect:/owners/{ownerId}"
}
}
}
Run the following Cover CLI command to create unit tests for this HTTP POST controller endpoint - we’ll use the fully-qualified class name of the PetController
class on the command line to only create tests for that class.
$ dcover create org.springframework.samples.petclinic.owner.PetController
Running this command will trigger Diffblue Cover to create a set of tests for our entire controller class. As a result, we’ll find a new test class PetControllerDiffblueTest
within src/test/java
:
@ContextConfiguration(classes = {PetController.class})
@ExtendWith(SpringExtension.class)
class PetControllerDiffblueTest {
@MockBean
private OwnerRepository ownerRepository;
@Autowired
private PetController petController;
@MockBean
private PetRepository petRepository;
@Test
void testProcessCreationForm() throws Exception {
// Arrange
when(petRepository.findPetTypes()).thenReturn(new ArrayList<>());
Owner owner = new Owner();
owner.setAddress("42 Main St");
owner.setCity("Oxford");
owner.setFirstName("Jane");
owner.setId(1);
owner.setLastName("Doe");
owner.setPets(new HashSet<>());
owner.setTelephone("6625550144");
when(ownerRepository.findById(anyInt())).thenReturn(owner);
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/owners/{ownerId}/pets/new", 1);
// Act and Assert
MockMvcBuilders.standaloneSetup(petController)
.build()
.perform(requestBuilder)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.model().size(3))
.andExpect(MockMvcResultMatchers.model().attributeExists("owner", "pet", "types"))
.andExpect(MockMvcResultMatchers.view().name("pets/createOrUpdatePetForm"))
.andExpect(MockMvcResultMatchers.forwardedUrl("pets/createOrUpdatePetForm"));
}
// more tests for this controller endpoint
}
This auto-created test class contains test methods for all controller endpoints of the PetController
class. Cover automatically writes a set of unit tests for each controller endpoint to cover various scenarios. We can immediately run the tests as Diffblue Cover ensures that the tests compile and execute successfully.
As you can see, the test class created by Diffblue Cover is a Java test class. Currently, Diffblue Cover only supports Java test classes as an output format. However, there’s a simple way to automatically convert this test to Kotlin, if needed - see below.
Convert Java unit tests to Kotlin
Converting Java unit tests into Kotlin using IntelliJ’s conversion feature facilitates a smoother transition for companies migrating from Java to Kotlin. This capability not only streamlines the adaptation process by automating the conversion of existing test suites, but also ensures that legacy tests remain functional and relevant in the new Kotlin codebase.
Such a feature is particularly valuable for maintaining test coverage and quality assurance during the migration, allowing teams to leverage Kotlin’s concise syntax and modern features without losing the robustness of their Java-based tests.
To convert Java unit tests into Kotlin in IntelliJ IDEA, open the Java test file in IntelliJ and select Code > Convert Java File to Kotlin File
from the menu.

For our auto-created Java test class PetControllerDiffblueTest
, we get the following - a quick, simple, and accurate conversion:
/**
* Method under test:
* [PetController.processCreationForm]
*/
@Test
@Throws(Exception::class)
fun testProcessCreationForm3() {
// Arrange
Mockito.`when`(petRepository!!.findPetTypes()).thenReturn(ArrayList())
val owner = Owner()
owner.address = "42 Main St"
owner.city = "Oxford"
owner.firstName = "Jane"
owner.id = 1
owner.lastName = "Doe"
owner.pets = HashSet()
owner.telephone = "6625550144"
Mockito.`when`(ownerRepository!!.findById(ArgumentMatchers.anyInt())).thenReturn(owner)
val requestBuilder = MockMvcRequestBuilders.post("/owners/{ownerId}/pets/new", 1)
requestBuilder.contentType("text/plain")
// Act and Assert
MockMvcBuilders.standaloneSetup(petController)
.build()
.perform(requestBuilder)
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.model().size(3))
.andExpect(MockMvcResultMatchers.model().attributeExists("owner", "pet", "types"))
.andExpect(MockMvcResultMatchers.view().name("pets/createOrUpdatePetForm"))
.andExpect(MockMvcResultMatchers.forwardedUrl("pets/createOrUpdatePetForm"))
}
Last updated
Was this helpful?