Can you make mockito (1.10.17) work with default methods in interfaces?

I am a big fan of mockito, unfortunately for one of my projects which uses Java 8, it fails on me...

Scenario:

public final class MockTest
{
    @Test
    public void testDefaultMethodsWithMocks()
    {
        final Foo foo = mock(Foo.class);

        //when(foo.bar()).thenCallRealMethod();

        assertThat(foo.bar()).isEqualTo(42);
    }

    @FunctionalInterface
    private interface Foo
    {
        int foo();

        default int bar()
        {
            return 42;
        }
    }
}

Unfortunately, the test fails and foo.bar() returns 0.

When I uncomment the when() line, I get a stack trace...

java.lang.NoSuchMethodError: java.lang.Object.bar()I
    at com.github.fge.lambdas.MockTest.testDefaultMethodsWithMocks(MockTest.java:18)

This is the latest stable version available on maven; googling around didn't tell me much about the status of mockito with regards to this new functionality in Java 8...

Can you make it work in some other way than implementing interfaces and spy() on them (this works)?

Answers


With mockito 2.x, JDK 8 default methods are supported.

With mockito 1.x it's not possible,


Old answer

Unfortunately it's not yet possible (mockito 1.10.19), from the README.md on the github'page

JDK8 status

Mockito should work fine with JDK8 if you stay away from default methods (aka defender methods). Lambda usage may work just as good for Answers. We're unsure about every JDK8 features at the moment, like serializing a mock that uses a lambda. Error report and pull request are welcome though (contributing guide).

EDIT 1: defender methods and default methods are different names for the same thing.

I hope for a mockmaker replacement that will handle java 8 opcodes properly for such cases as some opcodes have a different semantic in Java 8.

EDIT 2: Updated the mockito readme, and this quote accordingly


I just tried Mockito 2.0.38-beta, and it already works in that version. But Mockito must be told explicitly to call the default implementation.

Foo foo = mock(Foo.class);
assertThat(foo.bar()).isEqualTo(0);

when(foo.bar()).thenCallRealMethod();
assertThat(foo.bar()).isEqualTo(42);

You can get around this limitation by implementing the interface (tested in Mockito 1.10.19):

public class TestClass {
  @Mock ImplementsIntWithDefaultMethods someObject;


  @Test public void test() throws Exception {
    // calling default method on mocked subtype works
    someObject.callDefaultMethod();
  }


  /* Type that implements the interface */
  static class ImplementsIntWithDefaultMethods implements IntWithDefaultMethod { }

  /* Interface you need mocked */
  interface IntWithDefaultMethod {
    default void callDefaultMethod { }
  }
}

I just ran into the same issue with Mockito (org.mockito:mockito-core:1.10.19). Problem is: I'm not able to change the Mockito version (2.7.22 would work) because of dependencies to org.springframework.boot:spring-boot-starter-test:1.4.3.RELEASE which we are using (Spring, Mockito issue).

The easiest solution I found is to implement the interface with a private abstract class within my test class and mocking that one (also compare to the solution of @Mihai Bojin). Doing it like this keeps you away from the hassle to also "implement" all methods required by the interface(s).

MWE:

public interface InterfaceWithDefaults implements SomeOtherInterface {
    default int someConstantWithoutSense() {
        return 11;
    }
}

public class SomeTest {
    private abstract class Dummy implements InterfaceWithDefaults {}

    @Test
    public void testConstant() {
        InterfaceWithDefaults iwd = Mockito.mock(Dummy.class);

        Assert.assertEquals(11, iwd.someConstantWithoutSense());
    }
}

Need Your Help

How do you convert cstring to NSString?

cocoa

I have been able to find methods like -[NSString stringWithCString:encoding:] but they do not seem to play well when the cstring is a pointer.

Change appcompat's SearchView text and hint color

android styles android-actionbar searchview

Does anybody know how to change the text color of the appcompat SearchView? I've spent 2 hours and tried several suggestions from SO and none works.