1

I'm pretty new to spring boot and kotlin. I've started with one basic app from net and writing unit test, but I'm getting following error:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: articleRepository.save(article) must not be null

Let me show you the code: Entity Class

@Entity
data class Article (
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    val id: Long = 0,

    @get: NotBlank
    val title: String = "",

    @get: NotBlank
    val content: String = ""
)

controller:

@PostMapping("/articles")
fun createNewArticle(@Valid @RequestBody article: Article) : Article {
    return articleRepository.save(article)
}

Repository:

@Repository
interface ArticleRepository : JpaRepository<Article, Long>

Test File:

RunWith(SpringRunner::class)
@SpringBootTest
class KotlinDemoApplicationTests {

lateinit var mvc: MockMvc

@InjectMocks
lateinit var controller: ArticleController

@Mock
lateinit var respository: ArticleRepository

@Before
fun setup() {
    MockitoAnnotations.initMocks(this)
    mvc = MockMvcBuilders.standaloneSetup(controller).setMessageConverters(MappingJackson2HttpMessageConverter()).build()
}

@Test
fun createBlog() {
    var article = Article(1, "Test", "Test Content")
    var jsonData = jacksonObjectMapper().writeValueAsString(article)
    mvc.perform(MockMvcRequestBuilders.post("/api/articles/").contentType(MediaType.APPLICATION_JSON).content(jsonData))
            .andExpect(MockMvcResultMatchers.status().isOk)
            .andDo(MockMvcResultHandlers.print())
            .andReturn()
}
}

When I'm running this test file, getting error mentioned above. Please help me with this.

Avv
  • 555
  • 1
  • 10
  • 18

1 Answers1

1

The problem is your ArticleRepository mock.

While you correctly inject it into your Controller, you're not specifiying what a call to save should return. It therefore returns null, which is not allowed in Kotin because you specified it as non-optional.

Either you allow your controller's createNewArticle to return null, by adding a ?, that is changing its signature to

fun createNewArticle(@Valid @RequestBody article: Article) : Article? {...}

Or you set-up the mock so that it does not return null, but an article.

@Before
fun setup() {
    MockitoAnnotations.initMocks(this)
    ...
    `when`(respository.save(any())
        .thenReturn(Article()) // creates a new article
}

(Alternatively, there's also Mockito's returnsFirstArg() in case you don't want to invoke the construtor.)


Note that using any() in this case will only work if you're using mockito-kotlin
If you don't want to use it, check this answer

Lovis
  • 9,513
  • 5
  • 31
  • 47