Agraj
Agraj

Reputation: 474

Mocking BiFunction with Spock Java/Groovy

Trying to mock a function that returns a BiFunction unsuccessfully.
The function looks like

public interface myInterface { 
  Optional<BiFunction<Object, Object, Object>> myAwesomeFunc()
}

Trying to mock like

def mockBiFunction = Mock(BiFunction)
mockMyInterface.myAwesomeFunc >> mockBiFunction 
mockBiFunction.apply(*_) >> mockReturnVal 

This results in

No signature of method: com.sun.proxy.$Proxy49.apply() is applicable for argument types: (org.spockframework.lang.SpreadWildcard) values: [*_]
Possible solutions: apply(java.lang.Object, java.lang.Object), any(), any(groovy.lang.Closure), every(), tap(groovy.lang.Closure), every(groovy.lang.Closure)
groovy.lang.MissingMethodException: No signature of method: com.sun.proxy.$Proxy49.apply() is applicable for argument types: (org.spockframework.lang.SpreadWildcard) values: [*_]
Possible solutions: apply(java.lang.Object, java.lang.Object), any(), any(groovy.lang.Closure), every(), tap(groovy.lang.Closure), every(groovy.lang.Closure)

Tried with

mockBiFunction(*_) >> mockReturnVal

That doesn't work either.

Edit: Tried with

mockBiFunction.apply(object1, object2) >> mockReturnVal

This fails with

Cannot invoke method rightShift() on null object
java.lang.NullPointerException: Cannot invoke method rightShift() on null object

When I have mocked it then why is it null ??

Upvotes: 1

Views: 665

Answers (2)

kriegaex
kriegaex

Reputation: 67287

Actually, your interface method returns an Optional, not a BiFunction. More precisely, it returns Optional<BiFunction<Object, Object, Object>>. Therefore, your interface mock needs to return an Optional as well when stubbing myAwesomeFunc(). That is what IMO is wrong with your code.

Here is my take:

package de.scrum_master.stackoverflow.q71602791

import spock.lang.Specification

import java.util.function.BiFunction

class BiFunctionMockTest extends Specification {
  def "mock BiFunction"() {
    given:
    def biFunction = Mock(BiFunction) {
      apply(*_) >> "dummy"
    }
    def myInterface = Mock(MyInterface) {
      myAwesomeFunc() >> Optional.of(biFunction)
    }
    def underTest = new MyInterfaceUser(myInterface: myInterface)

    expect:
    underTest.doSomething().get().apply("foo", "bar") == "dummy"
  }

  interface MyInterface {
    Optional<BiFunction<Object, Object, Object>> myAwesomeFunc()
  }

  static class MyInterfaceUser {
    MyInterface myInterface

    def doSomething() {
      myInterface.myAwesomeFunc()
    }
  }
}

Upvotes: 1

Agraj
Agraj

Reputation: 474

Ah looks like all I had to do was to use a function as the mock return value from the BiFunction so something like following works

def mockMyAwesomeFunc = abc -> mockReturnVal 
mockBiFunction.apply(object1, object2) >> mockMyAwesomeFunc

instead of doing

mockBiFunction.apply(object1, object2) >> mockReturnVal

Feeling really stupid now !!

Edit -- Updating the answer to more closely reflect the actual working code - this is what worked

def mockBiFunction = Mock(BiFunction)
mockMyInterface.myAwesomeFunc >> Optional.of(mergeBiFunction)
mergeBiFunction.apply(_, _) >> (a, b) -> {
    return mockValue
}

Upvotes: 0

Related Questions