1

I'm trying to test the following class

@Component
public class StreamListener {

  @Value("${kafkaMessageExpiration.maxExpirationInMilliseconds}")
  private long messageExpirationTime;

  public void handleMessage(Payment payment) {
    logIncomingDirectDepositPayment(payment);

    if (!isMessageExpired(payment.getLastPublishedDate())) {
      messageProcessor.processPayment(payment);
    }
  }

  private boolean isMessageExpired(OffsetDateTime lastPublishedDate) {
    return ChronoUnit.MILLIS.between(lastPublishedDate.toInstant(), Instant.now()) > messageExpirationTime;
  }

}

I'm getting a "changed conditional boundary → SURVIVED" message on the condition in isMessageExpired().

I have the following tests which test when the difference is less than messageExpirationTime and when the difference is greater than messageExpirationTime.

@BeforeEach
void init() {
  ReflectionTestUtils.setField(streamListener, "messageExpirationTime", 60000);
}


@Test
void handleMessage() {
  Payment payment = TestObjectBuilder.createPayment();

  streamListener.handleMessage(incomingDirectDepositPayment);

  verify(messageProcessor).processDirectDepositPayment(incomingDirectDepositPayment);
}

@Test
void handleMessage_expired_message() {
  Payment payment = TestObjectBuilder.createPayment();
  payment.setLastPublishedDate(OffsetDateTime.now(ZoneId.of("UTC")).minusMinutes(10));

  streamListener.handleMessage(incomingDirectDepositPayment);

  verify(messageProcessor, never()).processDirectDepositPayment(incomingDirectDepositPayment);
}

I suspect the problem is that I don't have a test where the difference is equal. Assuming that is what I'm missing, I don't know how to get the difference to be equal. Any suggestions on how I can kill this mutation?

BTW, I'm using Java 11, JUnit 5 and PITest 1.6.3

Steve B
  • 557
  • 2
  • 7
  • 23

1 Answers1

1

This issue is this

Instant.now()

If time is one of the inputs your code depends on you need to make that explicit so you can control it.

This is normally achieved by injecting a java.util.Clock (held as a field, injected via the constructor). Your call to Instant.now() can then be replaced with clock.instant() and the code becomes properly unit testable.

henry
  • 5,923
  • 29
  • 46