Question

Let's say we have an interface which has two methods:

public interface MyInterface {
    public SomeType first();
    public SomeType second();
}

This interface is implemented by MyInterfaceImpl. Inside the implementation, first() calls second() to retrieve some results.

I want to build a unit test which would assert things coming out of first() based on what comes out of second(), similar to:

1  public class MyInterfaceTest {
2     private MyInterface impl = new MyInterfaceImpl();

4     @Test
5     public void testFirst() {
6         // modify behaviour of .second()
7         impl.first();
8         assertSomething(...);

10        // modify behaviour of .second()
11        impl.first();
12        assertSomethingElse(...);
13    }
14 }

Is there an easy way to create a mock on the line 2 so that all calls to selected methods (e.g. first()) would be invoked directly (delegated to MyInterfaceImpl) whereas some other methods (e.g. second()) replaced with mock counterparts?

This is actually very easily doable with PowerMock for static methods, but I need something similar for dynamic ones.

Solutions based on

MyInterface mock = EasyMock.createMock(MyInterface.class);
MyInterface real = new MyInterfaceImpl();
EasyMock.expect(mock.first()).andReturn(real.first()).anyTimes();
EasyMock.expect(mock.second()).andReturn(_somethingCustom_).anyTimes();

are not good enough, especially for interfaces having lots of methods (lots of boilerplate). I need the forwarding behaviour as real actually depends on other mocks.

I would expect something like this to be handled by a framework, and not by my own class. Is this achievable?

Was it helpful?

Solution

How about good old subclassing? I mean something like

private MyInterface impl = new MyInterfaceImpl(){
    public final MyInterface mock = EasyMock.createMock(MyInterface.class);
    @override //only the method you need to mock
    public SomeType second(){
        return mock.second();        
    }
}

@Test
public void testFirst() {
    // modify behaviour of .second()
    EasyMock.expect(impl.mock.second()).andReturn("What I want").anyTimes();
    impl.first();
    assertSomething(...);

    // modify behaviour of .second()
    EasyMock.expect(impl.mock.second()).andReturn("Now I want something else").anyTimes();
    impl.first();
    assertSomethingElse(...);
}

You are not testing the exact class you want to test, but an anonymous subclass. But we can assume subclassing works ok in Java.;-)

OTHER TIPS

It sounds like you should quite possibly have separate interfaces for first() and second(), if the implementation of first() has to call second(). You could then split the implementation too, and mock out second() while testing first(). Without a more concrete example of what first() and second() are, it's tricky to say for sure.

Using EasyMock on the implementation class to mock out only second() call might work, but you don't seem to want to do that anyway. This may require telling EasyMock to pass calls to first() through to the normal implementation - I'm not sure.

Another option might be to subclass the implementation within the test class (as a nested class) allowing you to override just second() for the purposes of testing. It's pretty ugly though.

Personally I don't like faking out part of a class just to test the rest. I'd much rather fake out all a class's dependencies.

Possibly you could use a Dynamic Proxy.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top