Mockk: cannot specify an answer for method call - unit-testing

I have the following method call in my Kotlin class:
myService.trigger(id, processVariables, transientVariables)
... where "id" is a String, "processVariables" is a Java Map<String, Object> and "transientVariables" is a Kotlin MutableMap<String, Any>.
How to I specify the answer to return in a unit test for this circumstance? I have tried the following:
every { myService?.trigger(MY_ID, any(), any()) } returns unit
... but I get an error when the unit test runs:
io.mockk.MockKException: no answer found for: MyService(#2).trigger(MY_ID, {}, {key=value})
Thanks in advance for any assistance.

A workaround that can be compiled and results in a successful test run is to populate the Map with values:
val map = mapOf("Key" to "Value")
every { processInstance.processVariables } returns map
every { myService?.trigger(EXECUTION_ID, map, any()) } returns unit

Related

Kotlin & MockK - mocking not working if a mocked method is called from another method

I have a problem with MockK.
I have a class:
#Service
class ItemServiceImpl(private val varPuObjectMapper: VarPuObjectMapper) : OutboundAdvicesService {
override suspend fun getItemsForWarehouse(warehouseId: String): ItemsDTO {
// do stuff
}
override suspend fun getPickingListsForWarehouse(warehouseId: String): PickingListsDTO {
val groupedOutboundAdvices = getItemsForWarehouse(warehouseId)
// do other stuff
}
}
and a test for this class:
class ItemServiceGroupingTest : FunSpec({
val warehouseId = "1"
val myObjectMapper = MyObjectMapper()
val itemService = mockk<ItemServiceImpl>()
beforeTest {
val items1 = myObjectMapper
.getObjectMapper()
.readValue(Mockups.ITEMS_1, ItemsDTO::class.java)
coEvery {
itemService.getItemsForWarehouse(warehouseId)
} returns items1
}
test("should get items for warehouse with ID 1") {
val itemsDTO = itemService.getItemsForWarehouse(warehouseId)
// assertions here
}
test("should get picking lists for warehouse with ID 1") {
val pickingLists = itemService.getPickingListsForWarehouse(warehouseId)
// assertions here
}
})
Now the first test passes successfully, but the second one fails:
no answer found for: ItemServiceImpl(#1).getPickingListsForWarehouse(1, continuation {})
io.mockk.MockKException: no answer found for: ItemServiceImpl(#1).getPickingListsForWarehouse(1, continuation {})
at app//io.mockk.impl.stub.MockKStub.defaultAnswer(MockKStub.kt:93)
From what I understand, this fails cause the getPickingListsForWarehouse method is not mocked. Is it possible to call a real method using MockK? I tried to use spyk instead of mockk, and I tried mockk with relaxed = true, but it got me nowhere...
The problem with the second test is that you are trying to call a method from a mock without specified behavior. The first test passes because you already set the value which should be returned for the method call itemService.getItemsForWarehouse(warehouseId) in this statement in beforeTest:
coEvery {
itemService.getItemsForWarehouse(warehouseId)
} returns items1
You have to do the same for getPickingListsForWarehouse or call a real method like:
every { itemService.getPickingListsForWarehouse(warehouseId) } answers { callOriginal() }
But then you have to use spyk instead of mock.
However, if you are asserting the object which you provided within the mock, you are not testing the real implementation of the method under test. You are just testing the mock, so if you change the implementation of your method this test still will be passing. beacuse it doesn't call your real object.

How to mock kotlin object for unit testing

I have a sample method(which I need to write test case) as given below,
fun setName(val auxName:String) {
val configUrl = getConfig(auxName)
}
I want to mock the getConfig method and return a specific string value.
getConfig is a method in a Kotlin Object as below,
object Configuration{
fun getConfig(auxName:String){
....
}
}
Below is the test that I tried
#Test
fun setTest()
{
val testname="test"
val testObject=Mockito.mock(Configuration::class.java)
doReturn("configTest").`when`(testObject).getConfig(Mockito.anyString())
setName(testname)
}
I am not getting any error but the method getConfig is not mocked. The actual implementation is executed. I tried using Powermockito also. Please help me with this
the problem is probably with singleton object, you can try this answer: https://stackoverflow.com/a/37978020/3703819

Using Kotlin and Mockito to mock functions taking vararg parameters

I'm having trouble utilizing Powermock, Mockito, and Kotlin to mock up a return value when
the function signature that needs overriden contains varargs.
Function to mock/override:
public BoundStatement bind(Object... values);
Test File:
class DbSessionTest {
var preparedStatement: PreparedStatement? = null
#Mock
var boundStatement: BoundStatement? = null
#Before
fun setup() {
initMocks(this)
whenever(preparedStatement?.bind(any())).thenReturn(boundStatement)
// Also, have tried it like this
whenever(preparedStatement?.bind(any<Array<Any>>())).thenReturn(boundStatement)
}
}
The fuction in the actual code is called like so:
internal fun createBoundStatement(query: String, vararg params: Any): BoundStatement {
val preparedStatement = prepare(query)
val boundStatement = preparedStatement.bind(*params)
return boundStatement
}
When I step through and the varargs are dereferenced, it turns into an Object[].
When the object array contains all the same type, everything works fine, but when
it contains type String and type Integer, the mock fails to happen and null is
returned.
Note: I have also included com.nhaarman.mockito_kotlin.any package for their specific
any function and anyVararg, but that did not work either.
What is the proper way to mock this so that no matter the type in the Object array,
it will always return the mocked value?
Nicholas Hauschild's answer make me think about removing powermock and just going with regular mockito and junit separately and that worked. Removing powermock and Upgrading mockito to v2.18.3 fixed the issue.

Grails Unit test and mocking addTo

I am trying to test the override of equals in a domain object to ensure that 'contains' works. The unit test mechanics are defying me, in spite of documentation and bugs saying that I should be able to mock addTo.
My test is:
#TestFor(Member)
#Mock([Member])
class MemberCategoryTests {
void testContains() {
MemberCategory schoolCat = new MemberCategory(name: "SCHOOL")
MemberCategory membersCat = new MemberCategory(name: "Members")
Member member = new Member(membershipNumber: "333333",
surname: "Tester",
forenames: "Jim",
preferredEmail: "mmm#yyy.com")
member.addToMemberCategories(schoolCat)
member.addToMemberCategories(membersCat)
MemberCategoryRedback memberCategoryRedback = new MemberCategoryRedback(name: "SCHOOL")
assert member.memberCategories.contains(memberCategoryRedback)
}
}
The error is:
No signature of method: au.com.interlated.civiLink.Member.addToMemberCategories() is applicable for argument types: (au.com.interlated.civiLink.MemberCategory)
The domain object isn't special. MemberCategory implements equals.
This document says #Mock([yyy]) should do the trick: Naleid upgrading to grails 2 testing as does unit testing addto
I feel you need two changes to make it work
1.Add MemberCategory to #TestFor, because your trying to add members to membercategirt then your code will become like this:
#TestFor(MemberCategory)
#TestFor(Member)
2.Also call save() after adding member.addToMemberCategories(membersCat), then your code will become some thing like this
if(!member.save(validate: true,flush:true,failOnError: true)) {
member.errors.each {
log.debug(it)
}
}
Hope this helps.

specs2: Is there a way to use doNothing while mocking with Mockito?

Let's say that I have a mocked trait Foo:
trait Foo {
def op(x: String): Unit
}
and I mocked this interface using
val mockedFoo = mock[Foo]
I want the method op to throw an exception second time I call it, e.g.
import org.specs2.mock.Mockito
import org.specs2.mutable.Specification
trait Foo {
def op(x: String): Unit
}
class DummySpec extends Specification with Mockito {
"dummy" should {
"test" in {
val mockedFoo = mock[Foo]
org.mockito.Mockito.doNothing().doThrow(new RuntimeException).when(mockedFoo).op(any[String])
mockedFoo.op("This one should work fine") should not(throwAn[Exception])
mockedFoo.op("This one should throw an exception") should throwAn[Exception]
}
}
}
Is there a way to do this in specs2 style? e.g.
mockedFoo.op(any[String]) returns Unit thenThrows new RuntimeException
but this doesn't compile.
Thanks!
The Unit return type makes things a bit trickier as you can't just chain:
returns "foo" thenThrows new RuntimeException
But you can still solve this problem if you use answers like below:
mockedFoo.op(anyString) answers {args => } thenThrows new RuntimeException
See if this works for you.