Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

unit testing - Mockito - Kotlin test throws Null Pointer Exception when trying to capture Pageable argument

I have written a really simple test for a method in my controller using Mockito

@Test
fun `get items based on category ID`() {
    val pageable: Pageable = PageRequest.of(5, 50)
    controller.get(10, pageable)

    val captor = ArgumentCaptor.forClass(Int::class.java)
    val pageableCaptor = ArgumentCaptor.forClass(Pageable::class.java)
    Mockito.verify(itemService).getItemsBasedOnCategoryID(captor.capture(), pageableCaptor.capture())
    assertEquals(captor.value, 10)
    assertEquals(pageableCaptor.value.pageSize, 50)
    assertEquals(pageableCaptor.value.pageNumber, 5)
}

But I get this exception

pageableCaptor.capture() must not be null
java.lang.NullPointerException: pageableCaptor.capture() must not be null
    at com.practice.ItemControllerTest.get items based on category ID(ItemControllerTest.kt:41)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

which I am not able to understand because when I test the method directly on the service layer using a similar code it passes the test. I have a workaround for this test but I am just trying to understand why this is not working. I would really appreciate some help with this.

If there is any other information that you would like me to add please feel free to let me know.

question from:https://stackoverflow.com/questions/65931441/mockito-kotlin-test-throws-null-pointer-exception-when-trying-to-capture-pagea

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The problem is that the pageable argument of the getItemsBasedOnCategoryID is non-nullable, while the return type of the ArgumentCaptor.capture is a platform type, which is considered by the Kotlin compiler as possibly nullable (and actually capture() returns null, that's how Mockito works). In such a case, the compiler generates null checks, when the type is used. You can see it in the decompiled code of your test:

@Test
public final void get_items_based_on_category_ID {
      ...
      Object var10002 = pageableCaptor.capture();
      Intrinsics.checkNotNullExpressionValue(var10002, "pageableCaptor.capture()"); <<- NPE
      var10000.getItemsBasedOnCategoryID(var4, (Pageable)var10002);
      ...
}

The trick is to somehow fool the compiler to prevent it from generating null-checks.

Option 1: Use mockito-kotlin library. It provides work-around for these kind of issues plus several additional tools. It might be your best choice, as probably you are going to face next issues, e.g. when using Mockito's any() argument matcher (same story, null- vs non-null mismatch)

Option 2: DIY:

  1. Firstly, explicitly declare ArgumentCapture's type parameter as non-nullable:
val pageableCaptor: ArgumentCaptor<Pageable> = ArgumentCaptor.forClass(Pageable::class.java)

Without the explicit declaration, the type of the pageableCaptor is ArgumentCaptor<Pageable!>!, i.e. a platform type.

  1. Then you are going to need a helper function:
@Suppress("UNCHECKED_CAST")
private fun <T> capture(captor: ArgumentCaptor<T>): T = captor.capture()

It seems to be a no-op function, but the point is that it does not return a platform type anymore: if the ArgumentCaptor's type parameter in non-nullable, so is the type of the function return value.

  1. And finally use this function instead of the ArgumentCaptor.capture():
Mockito.verify(itemService).getItemsBasedOnCategoryID(captor.capture(), capture(pageableCaptor))

Now the Kotlin compiler believes that capture(pageableCaptor) never returns null, so it does not generate any null-checks.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...