Question

I am trying to write some junit for a class which is using CountDownLatch and I am using jmockit library for junit testing.

public class MappedData {

    private static final AtomicReference<Map<String, Map<Integer, String>>> mapped1 = new AtomicReference<Map<String, Map<Integer, String>>>();
    private static final AtomicReference<Map<String, Map<Integer, String>>> mapped2 = new AtomicReference<Map<String, Map<Integer, String>>>();
    private static final CountDownLatch firstSet = new CountDownLatch(1);

    public static Map<String, Map<Integer, String>> getMapped1Table() {
    try {
        firstSet.await();
    } catch (InterruptedException e) {
        throw new IllegalStateException(e);
    }
    return mapped1.get();
    }

    public static Map<String, Map<Integer, String>> getMapped2Table() {
    try {
        firstSet.await();
    } catch (InterruptedException e) {
        throw new IllegalStateException(e);
    }
    return mapped2.get();
    }
}

What is the easiest way to make sure that in the getMapped1Table and getMapped2Table method - I am able to throw an InterruptedException so that I can cover that scenario as well. If you take a look into those two methods, I have a catch block which I am not able to cover.

MappedData.getMapped1Table()

Is there any way I can make sure that my above two methods are throwing InterruptedException?

Update:-

What I am trying to do is - how to get firstSet.await() to throw an InterruptedException when I am junit testing.

Was it helpful?

Solution 2

Here is the simplest way to write the test with JMockit:

public class MappedDataTest
{
    @Test
    public void getMappedTableHandlesInterruptedException(
        @Mocked final CountDownLatch anyLatch) throws Exception
    {
        final InterruptedException interrupt = new InterruptedException();
        new NonStrictExpectations() {{ anyLatch.await(); result = interrupt; }};

        try {
            MappedData.getMapped1Table();
            fail();
        }
        catch (IllegalStateException e) {
            assertSame(interrupt, e.getCause());
        }
    }
}

OTHER TIPS

Call the method in a sperate thread, then interrupt that thread:

Thread t = new Thread(new Runnable(){
   public void run(){
      MappedData.getMappedTable();
    }
});

t.start();

t.interrupt();

You can do it with a mocking library such as Mockito or EasyMock. You will need a way to inject the mock dependency. Generally this is done through a constructor, but since your field is static you'll probably want to add a setter.

public static void setFirstSet(CountDownLatch latch)
{
    firstSet = latch;
}

The rest of this example is for Mockito.

In your test, create a mock CountDownLatch:

CountDownLatch mockLatch = mock(CountDownLatch.class);

Then stub the method to throw the exception:

when(mockLatch.await()).thenThrow(new InterruptedException());

Next inject the mock:

MappedData.setFirstSet(mockLatch);

Finally call the method under test:

Map<String, Map<Integer, String>> result = MappedData.getMapped1Table();

I've never used jmockit, but from a quick a quick google search suggests this is the way to do it:

final CountDownLatch mockLatch = new CountDownLatch();
new Expectations(mockLatch){
    {
        mockLatch.await();
        result = new InterruptedException();
    }
};
MappedData.setFirstSet(mockLatch);
Map<String, Map<Integer, String>> result = MappedData.getMapped1Table();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top