Is there a way to get the MethodDescription that matched? - byte-buddy

I'm "in" the intercept() method of DynamicType.Builder, right "after" a method has matched in the method() method. For example:
builder
.method(elementMatcher)
.intercept(/* here I am! */)
For a variety of reasons, I need the MethodDescription that was matched to be available "inside" that intercept() invocation. Is there any recipe that will give it to me?
I think I can probably abuse ElementMatchers#cached(ElementMatcher, ConcurrentMap) for this but I stress "abuse". 😄

The intercept method takes an Implementation which in turn returns a ByteCodeAppender. The latter accepts the instrumented method as an argument. You can use Implementation.Simple to direcly supply a byte code appender.

Related

Mockito - Is it possible to deep mock a void method call to do nothing?

I wanted to know if it is possible to "deep mock" a void method call without breaking out the call chain, using Mockito.
This is an example for the original call I want to mock:
obj.getSomething().add(3);
where "add"'s return type is void.
I tried:
doNothing().when(obj).getSomething().add(3)
and:
doNothing().when(obj.getSomething()).add(3) //wont work since "when" expects a mock.
I also failed using Mockito.when(...) since it does not work with void methods.
I do not want to break the call up since it will be very cumbersome for fluent API calls that are much longer.
Is there an official solution / workaround for this scenario?
Thanks :)
If the value returned by getSomething is not a mock, it won't work.
Return value of getSomething should be a mock and it will allow to assign mock behavior for that value.
Something someMock = mock(Something.class);
when(obj.getSomething()).thenReturn(someMock);
doNothing().when(someMock).add(3);

How do I use MethodCall.invoke(someElementMatcher) to create a MethodCall representing a method I subsequently define in an instrumented type?

I am using ByteBuddy to generate a class.
Prior to working with DynamicType.Builder, I was going to store a MethodCall as an instance variable:
private final MethodCall frobCall =
MethodCall.invoke(ElementMatchers.named("frob")); // here I invoke a method I'm going to define as part of the instrumented type
Then later in my generation logic for the instrumented type I define the frob method to do something:
.defineMethod("frob")
.intercept(...etc....) // here I define frob to do something
…and I define the (let's say) baz method to invoke frob:
.defineMethod("baz")
.withParameter(...) // etc.
.intercept(frobCall); // invokes "frob", which I've just defined above
(I am trying to keep this simple and may have mistyped something but I hope you can see the gist of what I'm trying to do.)
When I make() my DynamicType, I receive an error that indicates that the dynamic type does not define frob. This is mystifying to me, because of course I have defined it, as you can see above.
Is there some restriction I am unaware of that prohibits ElementMatchers from identifying instrumented type methods that are defined later? Do I really have to use MethodDescription.Latent here?
It should match all methods of the instrumented type. If this is not happening as expected, please set a breakpoint in MethodCall.MethodLocator.ForElementMatcher to see why the method is not showing up. I assume it is filtered by your method matcher.
I noticed however that it did not include private methods which is now fixed and will be released within Byte Buddy 1.10.18.

Kotlin syntax issue

Sorry for the terrible title, but I can't seem to find an allowable way to ask this question, because I don't know how to refer to the code constructs I am looking at.
Looking at this file: https://github.com/Hexworks/caves-of-zircon-tutorial/blob/master/src/main/kotlin/org/hexworks/cavesofzircon/systems/InputReceiver.kt
I don't understand what is going on here:
override fun update(entity: GameEntity<out EntityType>, context: GameContext): Boolean {
val (_, _, uiEvent, player) = context
I can understand some things.
We are overriding the update function, which is defined in the Behavior class, which is a superclass of this class.
The update function accepts two parameters. A GameEntity named entity, and a GameContext called context.
The function returns a Boolean result.
However, I do not understand the next line at all. Just open and close parentheses, two underscores as the first two parameters, and then an assignment to the context argument. What is it we are assigning the value of context to?
Based on IDE behavior, apparently the open-close parentheses are related to the constructor for GameContext. But I would not know that otherwise. I also don't understand what the meaning is of the underscores in the argument list.
And finally, I have read about the declaration-site variance keyword "out", but I don't really understand what it means here. We have GameEntity<out EntityType>. So as I understand it, that means this method produces EntityType, but does not consume it. How is that demonstrated in this code?
val (_, _, uiEvent, player) = context
You are extracting the 3rd and 4th value from the context and ignoring the first two.
Compare https://kotlinlang.org/docs/reference/multi-declarations.html .
About out: i don't see it being used in the code snippet you're showing. You might want to show the full method.
Also, maybe it is there only for the purpose of overriding the method, to match the signature of the function.
To cover the little bit that Incubbus's otherwise-great answer missed:
In the declaration
override fun update(entity: GameEntity<out EntityType>, // …
the out means that you could call the function and pass a GameEntity<SubclassOfEntityType> (or even a SubclassOfGameEntity<SubclassOfEntityType>).
With no out, you'd have to pass a GameEntity<EntityType> (or a SubclassOfGameEntity<EntityType>).
I guess that's inherited from the superclass method that you're overriding.  After all, if the superclass method could be called with a GameEntity<SubclassOfEntityType>, then your override will need to handle that too.  (The Liskov substitution principle in action!)

Calling OCMStub and OCMReject on the same method

I've been attempting to write some fail fast tests using OCMReject. However I've found that if OCMStub is used in conjunction with OCMReject, this test will pass
id _mockModel = OCMProtocolMock( #protocol( CTPrefModelProtocol));
//It doesn't seem to matter what order these two are in, the test behaves the same
OCMStub([_mockModel getPreferences]);
OCMReject([_mockModel getPreferences]);
[_mockModel getPreferences];
Even though it should clearly fail because I'm calling the function that I've set in the OCMReject method.
I realise I can just stub getPreferences whenever I'm expecting a result from it and remove it from this test, but largely that means if I've set a stub on getPreferences in my setUp method, any test that calls OCMReject([_mockModel getPreferences]) will just be ignored.
Why am I not able to use OCMStub and OCMReject together? Is it because OCMStub alters getPreferences somehow and as a result whenever I call this method, it actually calls some other method instead?
So apparently I can't read. Reading through the OCMock 3 Documentation, under the limitations heading 10.2
Setting up expect after stub on the same method does not work
id mock = OCMStrictClassMock([SomeClass class]);
OCMStub([mock someMethod]).andReturn(#"a string");
OCMExpect([mock someMethod]);
/* run code under test */
OCMVerifyAll(mock); // will complain that someMethod has not been called
The code above first sets up a stub for someMethod and afterwards an
expectation for the same method. Due to the way mock objects are
currently implemented any calls to someMethod are handled by the stub.
This means that even if the method is called the verify fails. It is
possible to avoid this problem by adding andReturn to the expect
statement. You can also set up a stub after the expect.
I suspect this same limitation exists for OCMReject as well. Hopefully this helps equally blind people like myself. A link to the documentation for the lazy.

Mocking void functions using EasyMock with dynamic behaviour

I need to mock a void function with EasyMock such that the first call returns an Exception, while the next succeeds.
For example:
this.myObject.move((String) EasyMock.anyObject());
EasyMock.expectLastCall().once().andThrow(new RetryableDependencyException());
EasyMock.expectLastCall().once();
But this is not working.
That's not going to work as the second expectLastCall() cannot find any call.
Have you tried this:
this.myObject.move((String) EasyMock.anyObject());
EasyMock.expectLastCall().once().andThrow(new RetryableDependencyException());
this.myObject.move((String) EasyMock.anyObject());
EasyMock.expectLastCall().once();
I know it's a bit verbose but it should get you sorted :)
The shortest is
myObject.move(anyString());
expectLastCall().andThrow(new RetryableDependencyException()).asStub();
which assumes that is doesn't matter if the method is called more than once after the exception. If it matters, it will be
myObject.move(anyString());
expectLastCall().andThrow(new RetryableDependencyException());
myObject.move(anyString());
Interesting facts:
You can chain andReturn
I highly suggest static imports to get a cleaner code
anyString is used to prevent the cast in String
once() is not required as it is the default
expectLastCall isn't required, calling the void method is enough to record a call without any side effect (like a throw)