Closed Novemser closed 5 years ago
Well, proceed
doesn't know the method execution is coming from a super.add
call, and if addLocal
did call add(o)
instead, we would expect B#add
to be executed, so I wouln't necessarily say this behavior is "wrong". In any case, I don't see an alternative to what proceed
does. Do you?
A potential work-around is to write the fake method as follows:
@Mock
public Object $advice(Invocation invocation) {
if (invocation.getInvokedInstance().getClass() == A.class) {
return invocation.proceed();
}
return null;
}
Yeah, while the JVM distinguishes super.add
via invokespecial
and this.add
via invokevirtual
, proceed
itself seems doesn't have enough information to infer this, thus will always be dynamically dispatched based on the invoked instance's type.
In the above work-around, invocation.getInvokedInstance().getClass()
will be B.class
rather than A.class
because the invoked instance is of type B
, so this work-around seems does not work?
Currently, I don't come up with an idea that could help me distinguish the two different cases(maybe intercepting the call stack and infer from the stack trace? But seems inefficient and subtle)...Do you have any suggestions?
Many Thanks!
To clariry, when proceed
gets called, it invokes the faked method (A#add
) again through Reflection (Method#invoke
), after having set an internal flag so that the faked method this times executes its real implementation instead of diverting into the fake method ($advice
). Reflection provides no way to execute a super.abc()
call, so a solution would have, necessarily, to not make this Reflection invoke call.
So, the only solution I can think of would be add a new kind of "proceed" method to the Invocation
class, something like proceedNoReturn()
(can't think of a good name at this time), which causes the faked method to complete its execution (and if it returns some value, the fake method would not be able to get it). This would be equivalent to "Before advice", while proceed
is equivalent to AOP's "Around advice".
Got it, thanks!
Please provide the following information:
1.49
, commitfbe6c3ca0c46c32e1e88c054a2abfdb80d4d308e
A
using faking API with AOP-style advice, but it seemssuper.add
in classB
is wrongly dispatched to the overrided version ofadd
.Way to reproduce just run the following junit test:
Produces exception like this:
jdk version: