easymock method matcher for class argument - java

I have a method with signature as follows:
public <T extends S> T foo(final Class<T> clazz){
.....
.....
}
How do I mock this method in easymock?
I tried following two lines in my test class but still the expected object is not returned, so I get NullPointerException.
Capture<Class<MyClass>> classCapture = new Capture<Class<MyClass>>();
expect(someObject.foo(EasyMock.capture(classCapture))).andReturn(testObject);
And testObject is initialized in the test class, which I want to get returned when
foo()
is called. Where am I doing wrong?

I'm not sure why you want to capture the variable in this instance, but your problem is the way you typed your command means you are looking for a method foo() without any arguments.
You need to you need to use and() to chain the capture and the argument matcher requirements for the method call:
expect(someObject.foo(EasyMock.and(
EasyMock.capture(classCapture),
anyObject()))
)
.andReturn(testObject);
Then after you call your mock in replay mode you can get the captured argument back with capture.getValue()
replay(someObject);
assertSame(testObject, someObject.foo(MyClass.class));
assertEquals(MyClass.class, classCapture.getValue());

Related

Not able to run ByteBuddy interceptor when #Morph argument is specified

I need to create a custom classes based on some input. What I have atm is this:
final Class service = ...;
final Method method = ...;
final DynamicType.Unloaded unloadedType = new ByteBuddy()
.subclass(Object.class)
.name(service.getClass().getSimpleName() + "DynamicResolver")
.defineMethod(
endpointName,
resolveReturnType(method),
Modifier.PUBLIC)
.withParameters(parameters)
.intercept(MethodDelegation
.withDefaultConfiguration()
.withBinders(Morph.Binder.install(Morphing.class))
.to(interceptor).andThen(
MethodCall.invoke(method).on(service).withArgument(arguments)
))
.make()
What I am doing here is creating a class with a single method that delegates to provided one. However, the created method and delegate method have a bit different parameters. The created method has one argument more (in parameters). The created method does not take that argument, hence the arguments array with argument indexes (one argument less).
So far it's OK. Now, I need to add additional argument when calling delegation method. For the sake of simplicity of the example, imagine we have to add one more string to delegate call.
As I saw from the documentation, the way to manipulate the arguments is using #Morph. So I did:
public interface Morphing<T> {
T invoke(Object[] args);
}
and my interceptor:
public class Interceptor {
#RuntimeType
public Object invoke(
#Morph final Morphing<Integer> m,
#AllArguments final Object[] args
) {
System.out.println("!!!");
return m.invoke(args);
}
}
Unfortunately, this is not working. When I remove the #Morph argument, the interceptor gets called.
What am I missing here?
EDIT: Is the #Morph used only for subclasses and not when delegating to another instance?
EDIT2: example
Byte Buddy is binding a method of the Object class such that your desired interceptor is no longer triggered. You can add filter(isDeclaredBy(MyInterceptor.class)) after the withDefaultConfiguration() to avoid this. Doing so, you will get an exception that Byte Buddy cannot bind any of your methods.
The reason that #Morph makes the class ineligable is that there is no super method to be called. In your example, you are defining a new method which does not have an original implementation. You'd need to override an existing method to use the annotation.

How do i verify the call to mocked instance when the instance takes "this" as parameter

I have a method which has call to event publisher, i want to verify the call to this publisher.
public void submitRegistrationForm(String registrationKey, RegistrationFormSubmitDTO registrationFormSubmitDTO) {
applicationEventPublisher.publishEvent(new RegistrationCompletedEvent(this, targetCustomerRegistration));
}
So, i mocked the applicationEventPublisher class and i had verified the call to it like this:
verify(applicationEventPublisher, times(1)).publishEvent(any(RegistrationCompletedEvent.class));
but i was told not to use any(), instead i need to build the concrete instance.
how can i verify the method which takes "this" as parameter.
You can use an argument captor to capture the RegistrationCompletedEvent and assert on it...
ArgumentCaptor<RegistrationCompletedEvent > argument = ArgumentCaptor.forClass(RegistrationCompletedEvent .class);
verify(applicationEventPublisher).publishEvent(argument.capture());
assertEquals("whatever", argument.getValue().something());

Mockito: how to mock doAnswer for a generic method

I have a class that, in essence, looks like this:
class Checkpointer {
public <Input,Output> Output runFunction(Input input, Function<Input,Output> function) {
Output output;
// Sometimes run the function, sometimes return an Output from a cache
return output
}
}
I would like to mock this class using Mockito doAnswer:
Checkpointer checkpointer; // mocked via #Mock annotation
Mockito
.doAnswer(/* ??? */)
.when(checkpointer)
.runFunction(Mockito.any(), Mockito.any());
The function I want to mock needs to be generic. Can this be done?
For example, my first attempt produced the following. Not only did I resort to Object as the type arguments for Function, but the compiler was still unhappy with unchecked casting:
Mockito.doAnswer((invocation) ->
{
// compiler is not happy with this cast V
Function<Object,Object> function = (Function<Object,Object>)invocation.getArguments()[1];
return function.apply(invocation.getArgument(0));
}).when(checkpointer).runFunction(Mockito.any(), Mockito.any());
If this can't be done, I think can try writing my own mock class extending the first and use Mockito.spy.
The problem here is that you insist on using getArguments, which returns an Object[]
Since you know the index of the Function argument, you can use getArgument(index), as you're doing the line after that.
final Function<String, String> argument = invocation.getArgument(1);
Is this what you're looking for? Type inference for the getArgument generic type is working fine.
If not, can you provide a more elaborate example?

EasyMock matcher for class data type

I am having nightmares with the syntax for this and easymock:
public void foo(Class<?> clazz);
EasyMock.expects(object.foo(EasyMock.isA(???)));
What should I be putting if my argument is String.class? I initially thought:
EasyMock.isA(((Class<?>)(String.class)).getClass())
Yet when I make the call foo(String.class) I get:
java.lang.IllegalStateException: missing behavior definition for the preceding method call:
You're attempting to verify a generic type that will be erased at runtime anyway.
Use a capture object instead:
Capture<Class<?>> classCapture = new Capture<Class<?>>();
EasyMock.expect(object.foo(EasyMock.capture(classCapture)));
// ... other test setup ...
Assert.assertEquals(classCapture.getValue(), String.class);
I think the following will also work as an expect statement if you don't want to use a Capture:
EasyMock.expects(object.foo(EasyMock.isA(String.class.getClass())));

Mockito: How to easily stub a method without mocking all parameters

I have a method i'd like to stub but it has a lot of parameters.
How can i avoid mocking all parameters but still stub the method.
Ex:
//Method to stub
public void myMethod(Bar bar, Foo foo, FooBar fooBar, BarFoo barFoo, .....endless list of parameters..);
I don't quite follow what problem you're having using Mockito. Assuming you create a mock of the interface that contains your myMethod() method, you can then verify only the parameters to the method that you are interested in. For example (assuming the interface is called MyInterface and using JUnit 4):
#Test
public void test() {
MyInterface myInterface = mock(MyInterface.class);
FooBar expectedFooBar = new FooBar();
// other testing stuff
verify(myInterface).myMethod(any(), any(), eq(expectedFooBar), any(), ...);
}
You'll need to do a static import on the Mockito methods for this to work. The any() matcher doesn't care what value has been passed when verifying.
You can't avoid passing something for every argument in your method (even if it's only NULL).
use mockito.any
if myobj mymethod accepts string, string, bar for instance
to stub a call
Mockito.when(myojb.myMethod(Mockito.anyString(),Mockito.anyString(),Mockito.any(Bar.class)))
.thenReturn(amockedobject);
to verify SteveD gave the answer already
Mockito.verify(myojb).myMethod(
Mockito.anyString(),Mockito.anyString(),Mockito.any(Bar.class)));
Create a wrapper class which calls the real method and fills in all the arguments but the ones you supply (a.k.a "delegation").
And at the next opportunity, file a bug against the project asking to move the parameters to a config object.

Categories