ClassCastException when using Mockito.thenAnswer

Viewed 47

I am new to Kotlin. I get exception when trying to use Mockito's thenAnswer method

Controller:

@RestController
class SampleRestController(
  val sampleService: SampleService
) {

  @PostMapping(value = ["/sample-endpoint"], consumes = [MediaType.APPLICATION_JSON_VALUE], produces = [MediaType.APPLICATION_JSON_VALUE])
  fun sampleEndpoint(@RequestBody values: List<String>): ResponseEntity<String> {
    val response = sampleService.serviceCall(values)
    return ResponseEntity.status(HttpStatus.OK).body(response)
  }
}

Service:

@Service
@Transactional
class SampleService {

  fun serviceCall(values: List<String>): String {
    return values.joinToString("")
  }

}

Test:

@ExtendWith(MockitoExtension::class)
internal class SampleRestControllerTest {

  @Mock
  private lateinit var sampleService: SampleService

  private lateinit var mockMvc: MockMvc

  private lateinit var objectMapper: ObjectMapper

  private lateinit var sampleRestController: SampleRestController

  @BeforeEach
  fun before() {
    MockitoAnnotations.initMocks(this)
    objectMapper = ObjectMapper()
      .registerModule(JavaTimeModule())
      .registerKotlinModule()
    sampleRestController = SampleRestController(sampleService)
    mockMvc = MockMvcBuilders.standaloneSetup(sampleRestController).build()
  }

  @Test
  fun doTest() {
    val testData = listOf("123", "456")
    //Mockito.`when`(sampleService.serviceCall(testData)).thenReturn("123456")
    //Mockito.`when`(sampleService.serviceCall(testData)).thenAnswer { invocation -> "123456" }
    Mockito.`when`(sampleService.serviceCall(testData)).thenAnswer { invocation -> {
      val numbers = invocation.getArgument<List<String>>(0)
      if ("123" == numbers[0] && "456" == numbers[1]) {
        "123456"
      } else {
        "654321"
      }
    } }

    val result: MvcResult = mockMvc.perform(
      MockMvcRequestBuilders.post("/sample-endpoint")
        .content(objectMapper.writeValueAsString(testData))
        .contentType(MediaType.APPLICATION_JSON_VALUE)
    )
      .andExpect(status().isOk)
      .andReturn()

    assertEquals("123456", result.response.contentAsString)

  }
}

The unit test is working fine when using the thenReturn() and also when using thenAnswer() without any if condition.

When I try to use thenAnswer with if condition then I get classCastException.

Probably because Kotlin only accepts non-null value? How do I resolve this issue.

1 Answers

Check this.

      @Test
      fun doTest() {
        val testData = listOf("123", "456")
        //Mockito.`when`(sampleService.serviceCall(testData)).thenReturn("123456")
        //Mockito.`when`(sampleService.serviceCall(testData)).thenAnswer { invocation -> "123456" }
        Mockito.`when`(sampleService.serviceCall(testData)).thenAnswer(Answer<Any?> { invocationOnMock: InvocationOnMock ->
          val values = invocationOnMock.getArgument<List<String>>(0)
          if ("123" == values[0] && "456" == values[1]) {
            return@Answer "123456"
          }
          return@Answer "654321"
        })
    
        val result: MvcResult = mockMvc.perform(
          MockMvcRequestBuilders.post("/sample-endpoint")
            .content(objectMapper.writeValueAsString(testData))
            .contentType(MediaType.APPLICATION_JSON_VALUE)
        )
          .andExpect(status().isOk)
          .andReturn()
    
        assertEquals("123456", result.response.contentAsString)
      }
Related