简体   繁体   中英

In a JUnit test, is there a way I can ensure that all assertions have been executed?

I have a Producer and a Consumer . Producer writes messages synchronously. The consumer is a thread that polls for messages every second.

I have a test like this:

@Test
public void shouldConsumeMessageWhenMessageIsProduced() {
    final Message expectedMessage = new Message("test");
    //consumer will poll every 1 second for a message
    consumer.poll((actualMessage) -> {assertThat(actualMessage), is(expectedMessage));
    producer.sendSynchronously(expectedMessage);
    Thread.sleep(3000);      
}

This test works. However, there is no way for me to ensure that the assertion was actually invoked.

I realize that I could use Mockito, but I also realize that this is more of an integration test than a unit test. But is there anyway in JUnit to ensure that all the assertions have been executed?

Please note since the assertion is in a lambda, I cannot increment a variable or set a flag.

I would make use either AtomicBoolean or MutableBoolean from your lambda expression depending on your preference. See the following code for an example:

import static org.junit.Assert.assertTrue;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.commons.lang.mutable.MutableBoolean;
import org.junit.Test;

public class AssertionLambdaTest {
    @Test
    public void assertExecutedWithAtomicBoolean() {
        AtomicBoolean myBoolean = new AtomicBoolean(false);
        doStuff(() -> {
            assertTrue(true);
            myBoolean.set(true);
        });
        assertTrue(myBoolean.get());
    }

    @Test
    public void assertExecutedWithMutableBoolean() {
        MutableBoolean myBoolean = new MutableBoolean(false);
        doStuff(() -> {
            assertTrue(true);
            myBoolean.setValue(true);
        });
        assertTrue(myBoolean.booleanValue());
    }

    private void doStuff(Runnable runner) {
        runner.run();
    }
}

Edit: I just realized that your question said " all assertions ". As such, you could equivalently use Apache's MutableInt class or Java's AtomicInteger in the same way, just incrementing until the correct number has been reached.

It seems that you want your test to wait until the assertion is triggered, probably with a time out. A CountDownLatch could do the job:

@Test
public void shouldConsumeMessageWhenMessageIsProduced() {
    final Message expectedMessage = new Message("test");

    CountDownLatch messageReceived = new CountDownLatch(1);

    //consumer will poll every 1 second for a message
    consumer.poll(actualMessage -> {
      assertThat(actualMessage, is(expectedMessage));
      messageReceived.countDown();
    }

    producer.sendSynchronously(expectedMessage);

    //wait until the message is received, but not more than one second
    //await returns false if it reaches the timeout
    assertTrue(messageReceived.await(1, SECONDS));
}

If you expect the assertion in the consumer to be triggered n times, you can change the initial count of the latch: CountDownLatch latch = new CountDownLatch(n); .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM