0

I'm trying to use Mockito to return some default values in tests but I get a 404 on it

My test:

@Test
fun `Should return 200, when sending a valid push notification`() {
    // Arrange
    Mockito.`when`(subscriptionStore.getSubscription{ it.peerID == validSubscription.peerID})
        .thenReturn(
            validSubscription
        )
    // Act
    val response = mockMvc.post("/push") {
        contentType = MediaType.APPLICATION_JSON
        content = objectMapper.writeValueAsString(validPushMessage)
    }
    // Assert
    response.andDo { print() }
        .andExpect {
            status { isOk() }
        }
}

and here's the method on the interface I try to mock:

interface SubscriptionStore {

    fun addSubscription(newSubscription: Subscription)

    fun getSubscriptions(): Collection<Subscription>

    fun getSubscription(predicate: (Subscription) -> Boolean): Subscription?
    fun deleteSubscription(peerID: String)
    fun updateSubscription(subscription: Subscription)

    class DuplicateElementException(msg: String) : Exception(msg)
}

and here's the usage of the mocked method that doesn't return what I told it but gives me 404:

override fun push(pushMessage: PushMessage) {
    val recipientSubscription = subscribeService.getSubscription(pushMessage.recipient)
        ?: throw NoSuchElementException("Recipient not found")
}

which calls this from my subscriptionStore

override fun getSubscription(PeerID: String): Subscription? = subscriptionStore.getSubscription { it.peerID == PeerID}
Wilkinson
  • 29
  • 5

1 Answers1

1

In Kotlin, 2 different lambdas with identical code are not considered equal:

val fun1: (Int) -> Boolean = {it > 5}
val fun2: (Int) -> Boolean = {it > 5}
println(fun1 == fun2) // false

This is why your stubbing fails - you pass different lambda in your test, and a different one in the actual code

To answer the original post: I would probably relax stubbing requirements on the predicate and use the ArgumentMatchers.any argument matcher

On top of that - selection of item by ID is typically exposed by DBs as a separate operation, as it is the fastest way to reach the element. Maybe it is worth adding to your API as well?

Lesiak
  • 22,088
  • 2
  • 41
  • 65
  • Well spotted. When I set mock expectations and the method takes a lambda (Function, Predicate etc.) I have to use (and I'm coding in Java here) `when(component.method(ArgumentMatcher.any(Predicate.class)).thenReturn(...)`. I believe this because there's no `equals` method on the lambda so the unit test lib is asserting equals on identity? – jeremyt Jul 02 '21 at 15:31
  • 1
    @jeremyt precisely, if equals is not overriden Object.equals is used – Lesiak Jul 02 '21 at 15:55