1

I always thought Mockito works some some kind of proxy and things like that. But now I found out, that Mockito allows me to do something like

class A {
  public String m1() {
    return m2();
  }

  public String m2() {
    return "Hello";
  }
}

class TestA {
  public testM1() {
    A a = Mockito.spy(A.class);
    when(a.m2()).thenReturn("Bye");
    Assert.assertEquals(a.m1(), "Bye");
  }
}

This wouldn't work with proxies. How does it do this? Could that technique be used to allow calling internal AOP-methods? (see Spring AOP not working for method call inside another method)

amram99
  • 699
  • 8
  • 19
mibutec
  • 2,929
  • 6
  • 27
  • 39

1 Answers1

3

Mockito does work with proxies, and does support spies. Your syntax is a bit off, though:

/* BAD */  A a = Mockito.spy(A.class);
/* GOOD */ A a = Mockito.spy(new A());

The reason for the different behavior is that a doesn't delegate to the parameter to spy(), but instead copies the field values to a brand new generated subclass of A with all of its methods overridden. Consequently, in Spring, references to this from within A refer to the unwrapped instance, where in Mockito references to this refer to the wrapped object—including the implicit reference to this in the m2() call within m1.

Though this sounds like it would allow for use of AOP, I'm not in a position to test that it works, and believe it would depend on the implementation details of Mockito and Spring AOP (and the order in which the wrapping happens).

[Editorial: Even if you can get the two code-generating systems to work well together, will you and your coworkers be able to read/understand/debug the test a year from now? :) ]

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251