47

I know that in order to mock how a method responds, you have to use

every { instanceX.methodB() } returns "42"

I'm trying to mock an iterator, for which you have to mock 2 methods hasNext() and next(), if hasNext() returns true always there will be an infinite loop, if it returns false from the beginning, next() will not return anything.

My question is: is there a way to mock individual calls one by one with mockk, as you can do in mockito ? I couldn't find anything in the docs.

BadChanneler
  • 1,450
  • 1
  • 12
  • 20
  • I'm getting data from cassandra using a library which returns a ResultSet, I need to test my service which is using that data, and I mock this ResultSet. – BadChanneler Sep 14 '18 at 05:48

4 Answers4

79

At the excellent post Mocking is not rocket science are documented two alternatives:

returnsMany specify a number of values that are used one by one i.e. first matched call returns first element, second returns second element:

    every { mock1.call(5) } returnsMany listOf(1, 2, 3)

You can achieve the same using andThen construct:

    every { mock1.call(5) } returns 1 andThen 2 andThen 3
p3quod
  • 1,449
  • 3
  • 13
  • 15
38

Use returnsMany or andThen construct with/instead of return.

oleksiyp
  • 2,659
  • 19
  • 15
5

Now I have a similar use-case, but for me answers is the appropriate solution as I already have an Iterator in place (and the returned iterator is actually a custom extension of Iterator):

every { mock.bogusIterator() /* : CustomIterator */ } answers { 
  val testIterator = testList.iterator() // just an Iterator
  every { hasNext() } answers { testIterator.hasNext() }
  every { next() } answers { testIterator.next() }
}

where testList contains some predefined values for the test.

returns always returns the value that is given to the function at that time. So using every { hasNext() } returns whatever will always return the value of whatever at that mock declaration time, regardless of whether whatever is mutable or not. On the other hand, with answer you always get the current value of what you return at the time of calling the function. In case someone gets confused by it ;-) Maybe also my further explanation confuses a bit :-)

Roland
  • 22,259
  • 4
  • 57
  • 84
1

I couldn’t answer the @GACy20, so I’m putting the answer to his question here.

Doubt: How does this apply if I want the first call to throw an exception and the second call to return a value?

You just need to do this:

every { thing.save(any()) } throws RuntimeException("Erro") andThen aRealValue