question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Allow Java 8 default ("defender") methods to be tested

See original GitHub issue

Java 8 allows default methods on interfaces. It seems like a legitimate use case to test these, by mocking the results of non-default methods of the interface. Here’s a (hypothetical) example that currently doesn’t work with Mockito:

import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;

public class Java8DefaultMethodTest {

    interface I {
        int i();
        default int f() {
            return i() + 1;
        }
    }

    @Test
    public void testFAddsOne() {
        I h = Mockito.mock(I.class);
        Mockito.when(h.i()).thenReturn(2);
        Assert.assertEquals(3, h.f());
    }
}

What is needed to make this work?

I’ve tried adding Mockito.when(h.f()).thenCallRealMethod() but this didn’t work. Also, there has been a related question (see Google Code ticket #456) which is similar in that it is related to Java 8 default methods but not the same because it deals with implementations of interfaces containing default methods.

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:7
  • Comments:29 (17 by maintainers)

github_iconTop GitHub Comments

7reactions
runeflobakkcommented, Aug 4, 2015

Typically, default methods are convenience methods which calls abstract methods which must be implemented by concrete classes. They offer some alternate ways to access the regular abstract interface methods, and as such the behaviour of the default methods are directly dependent on how abstract methods are stubbed (or not). Trivial example:

interface A {
  byte[] process(InputStream in);

  default byte[] process(byte[] bytes) {
    return process(new ByteArrayInputStream(bytes));
  }
}

When mocking A, I am only interested in stubbing the process(InputStream in)method, and not worry about if my code calls the method accepting an InputStream or a byte[] argument.

I use the following code to say “call all real default methods”:

mock(A.class, withSettings()
   .defaultAnswer(invocation -> invocation.getMethod().isDefault() ? invocation.callRealMethod() : RETURNS_DEFAULTS.answer(invocation)));

Just wanted to tell about my use case, and maybe it is such a common case that the API should offer some easy way to do just that? This enables me to just stub the abstract method, and the result of the default method depends on the abstract method.

(And I really wish it was possible to define final default methods in Java interfaces, but that’s another discussion 😉 )

1reaction
hbfcommented, Jul 14, 2016

@raphw You say that the test

    interface I {
        int i();
        default int f() {
            return i() + 1;
        }
    }

    @Test
    public void testFAddsOne() {
        I h = Mockito.mock(I.class);
        when(h.i()).thenReturn(2);
        when(h.f()).thenCallRealMethod();
        assertEquals(3, h.f());
    }

passes for you. I’m trying this against Mockito 1.10.19 and it fails:

java.lang.NoSuchMethodError: java.lang.Object.f()I

Are you using the 2.x branch?

Read more comments on GitHub >

github_iconTop Results From Across the Web

Purpose of Default or Defender methods in Java 8
One example is the Predicate interface which has only one abstract method ( test ) while providing default methods for negating a Predicate...
Read more >
What is Default, Defender or Extension Method of Java 8 with ...
Methods with default keywords are known as default methods or defender methods in Java. Before Java 8, it was virtually impossible to change...
Read more >
Default Methods In Java 8 - GeeksforGeeks
Default methods are also known as defender methods or virtual extension methods. Static Methods: The interfaces can have static methods as well ...
Read more >
What is Default or Defender Methods of Java 8 - Java67
Default methods, also known as virtual extension methods or defender methods is a non-abstract method, which can be declared inside an interface in...
Read more >
Introduction to Default Methods (Defender Methods) in Java 8
The same challenge was faced while enhancing the Collections API in Java 8 to support lambda expressions in the API. To overcome this...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found