user2312807
user2312807

Reputation: 21

Is there any tool that automates stubbing mock object responses? (using jmock, mockito or easy mock)

Question: Is there any tool that automates stubbing or mock object responses (using jmock, mockito or easy mock)?

I have to write unit tests against a method that has dependencies on Amazon AWS services (SQS/Simple Queue Service, and DynamoDB). Stubbing mock object responses tends to be very tedious and hard to maintain for me. So, I thought that it would be nice if we record and replay stubbed responses using Java proxy (over CGLib or javassist). I thought about implementing such an idea by myself, but I'd like to check if anyone has ever implemented such an idea.

Upvotes: 1

Views: 926

Answers (3)

tddmonkey
tddmonkey

Reputation: 21184

I would recommend against doing this completely. Mocking against libraries you don't own is just asking for trouble (as you're already seeing) and only confirms that you're interacting with the library in the way you think you should.

If you have code that interacts with SQS/DynamoDb then write integration tests that actually go and hit SQS and DynamoDb - they will give you a much higher level of confidence than unit tests and will not be brittle. DynamoDb also has an in-memory local instance you can spin up just for this purpose

Upvotes: 1

Steve Freeman
Steve Freeman

Reputation: 2707

easymock did exactly that in the old days, but we find such tests tend to be brittle as the code changes. My experience is that if maintaining stubs in tests is tedious then that's a clue about the design of the tested code that should be listened to. There probably should be more smaller objects in there.

Upvotes: 1

user2312753
user2312753

Reputation: 16

I thought about the same functionality, and ended up implementing it by myself over Mockito framework rather than CGLib directly. I heard that someone enabled Mockito on Android Java platform, so that I can easily port my tool that uses Mockito on Android. But, as far as I know, we cannot port any function that depends on CGLib or Javaassit at this time around.

I have open-sourced my tool named 'bimock' (bi-directional mock) which has two modes. When in Record mode, it records method invocations with return values or exceptions into a resource file in the JSON format. When in Replay mode, it sets up method invocations and answers out of the resource file when it starts up, and replays answers of returns or throws. See this example, where I records a Java object's public method responses and replays them from a JSON file.

You should be able to use this tool against various dependencies not only for Amazon AWS SDK object, but also JDK objects such as HashMap, ArrayList, ByteBuffer, and the like.

public class BimockTest {
    private Mode mode = Mode.Replay;
    private PojoMapper pojoMapper = new PojoMapper(new BimockModule());
    private Bimock bimock = new Bimock(pojoMapper);

    @Test
    public void testRecordAndReplayMap() throws IOException {
        val map = bimock.of(new HashMap<String, Integer>(), mode, new File("src/test/resources/test-record-and-replay-map.json"));
        assertThat(map.put("abc", 3), equalTo(null));
        assertThat(map.size(), equalTo(1));
        assertThat(map.get("abc"), equalTo(3));
    }

    @Test
    public void testRecordAndReplayList() {
        List<Long> list = new ArrayList<Long>();
        list = bimock.of(list, mode, new File("src/test/resources/test-record-and-replay-list.json"));
        try {
            assertThat(list.remove(-1), nullValue());
            fail();
        } catch (ArrayIndexOutOfBoundsException e) {
            assertThat(e.getMessage(), equalTo("-1"));
        }
        assertThat(list.add(100L), equalTo(true));
        assertThat(list.toArray(new Long[1]), equalTo(new Long[] { 100L }));
    }
}

Upvotes: 0

Related Questions