spockframework / spockframework/spock

Mock/Spy interaction verification withing specific time frame (with timeout)

Open
#1,661 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

new feature request-for-comments
Dominant language
Java
Stars
3.6k
Forks
483
PR merge metrics
No merged PRs in 30d

Description

Is your feature request related to a problem?

Testing asynchronous code (schedules, Kafka/RabbitMQ), an expected interaction might be triggered with some delay (e.g. 60ms). The regular verification construction fails immediately and an artificial wait before it is required (or some other hacks workarounds), what reduces the readability.

Describe the solution you'd like

An ability to define optional timeout to wait for an interaction before failing the assertion. E.g.

then:
   1.withTimeout(50) * orderFacadeMock.confirmOrder(ORDER_NUMBER)
   (1.._).withTimeout(Duration.ofSeconds(1)) * orderFacadeMock.getOrderStatus(_)
Describe alternatives you've considered

As a workaround, I've been usually using some (thread safe) boolean or counter in the stubbing, to verify the number of interactions. However, it makes code less readable and suppress the "Unmatched invocations" reporting.

Recently @Vampire proposed a nicer variant of that approach with CountDownLatch, which eliminates the second limitation, but still requires extra elements and obscures the code.

given:
  ...
  OrderFacade orderFacadeMock = Mock()
  def latch = new CountDownLatch(EXPECTED_NUMBER_OF_ORDER_CONFIRMATIONS)
when:
  kafkaTemplate(ORDER_CONFIRMED_TOPIC_NAME, ORDER_NUMBER)
then:
  latch.await(1000, SECONDS) || true
then:
  //orderConfirmed() should be called when Kafka consumer received a message from a designed topic
  EXPECTED_NUMBER_OF_ORDER_CONFIRMATIONS * orderFacadeMock.orderConfirmed(ORDER_NUMBER) >> { latch.countDown() }
Additional context
  1. I didn't check if the DSL modification (to add withTimeout() to a number of range) can be applied only within the scope of the mock assertion (not to every number "everywhere").
  2. I don't know, if there isn't any obstacles in the internal implementation of the interaction verification (e.g. that it is moved to the end of the when block.
  3. In Mockito it would be verify(orderFacadeMock, timeout(200)).orderConfirmed(ORDER_NUMBER).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

No files or tests are named. Start by tracing Spock's interaction-verification DSL and its timing within the when block, then define focused asynchronous tests for the proposed timeout forms and confirm they preserve unmatched-invocation reporting.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy, java
Domain
testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.