10

Consider the following sample MockUp of a class Foo that intercepts Bar in the constructor and then implements toString() in terms of Bar;

public class FooStub extends MockUp<Foo> {

    private Bar bar;

    @Mock
    public void $init(Bar bar) {
        this.bar = bar;
    }

    @Mock
    public String toString() {
        return bar.toString();
    }
}

If Foo happens to override toString() all works fine. Otherwise though, you get a IllegalArgumentException : "Matching real methods not found for the following mocks". I understand from here that JMockit does not look in base classes and therefore cannot find a toString() method to mock.

Assuming I can't modify the Foo class (in reality I can, but just for the sake of argument), is there any way to mock toString() just for this Foo class?

To be clear, I want to mock all instances of this class, not just one instance (that has easy solutions that do no require a MockUp).

Bogdan Calmac
  • 7,993
  • 6
  • 51
  • 64
  • 2
    Possible duplicate of [Jmockit: Can't mock method toString of net.android.Uri class](https://stackoverflow.com/questions/41561351/jmockit-cant-mock-method-tostring-of-net-android-uri-class) – Jotunacorn Jun 01 '17 at 08:37

1 Answers1

0

JMockit will mock all super-classes up the class hierarchy up to, but excluding java.lang.Object.

You could define private final class in your test which extends Bar by overriding toString() which delegates to Bar's toString() by calling super.toString():

private final class Baz extends Bar {
    @Override
    public String toString() {
        return super.toString();
    }
}

Now all you have to do in your mock is to delegate via Baz not Bar.

This way you got concrete yet transparent implementation of toString() which you can mock without touching Bar class which is potentially out of your control.

diginoise
  • 7,352
  • 2
  • 31
  • 39