Mocking the sort method from Collections - java

I have a code that I want to unit test. The code uses Collections.sort method providing it with our own sweet comparator something like :
List<Something> something = somethingService.doSomething(someParameter);
Collections.sort(something, somethingComparator);
Now while testing the function I am mocking the somethingService and stubbing the doSomething method like :
List<Something> mockList = Mockito.mock(List.class);
Mockito.when(somethingService.doSomething(anyInt())).thenReturn(mockList);
and I am mocking the Collections as :
PowerMockito.mockStatic(Collections.class);
PowerMockito.doNothing().when(Collections.class, "sort", anyListOf(Something.class), anyOf(Comparator.class));
But it is giving me :
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected
You cannot use argument matchers outside of verification or stubbing.
Now I do know that if we are using argument matchers in any param of a function we need to provide matchers to all the params. But here is it possible to do the same and if not then what is the existing workaround?

You are using PowerMock to mock a system class from the JDK, design wise it's really, really nasty. Seriously one should really think over his motivation to use Powermock as the author himself is.
Powermock cannot really mock directly static methods from system class, you have to create wrappers around the system calls, as documented in the wiki.
I would strongly advises you to extract some sorting strategy, that you could mock with just Mockito.

Related

Translate isEqualToComparingFieldByFieldRecursively to my Spock Test

I am translating all my Junit Tests into Spock Tests and I don't want to use any "Assert methods". Therefore I have to translate the method isEqualToComparingFieldByFieldRecursively into my Groovy class. I am not sure, if I understood the function of the method correctly.
assertThat(validationMessage).isEqualToComparingFieldByFieldRecursively(provider.createValidationMessageDto());
In this case validationMessage is a DTO-Object and provider.createValidationMessageDto returns the same kind of DTO-Object. Does there already exist any similar method or do I have to code a new own method, which checks validationMessage? And if so, what should the method do?
Thanks for your answers. 😊
If the validation message DTO doesn't provide a proper equals methods, then sticking with isEqualToComparingFieldByFieldRecursively might be your best solution.
While Spock has great implicit assertion, something like reflective field-by-field compare isn't directly supported.
You could use Spock's support for Hamcrest and it's samePropertyValuesAs to write:
import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs
import static spock.util.matcher.HamcrestSupport.that
// ...
expect:
that validationMessage, samePropertyValuesAs(provider.createValidationMessageDto()
However, that does not do recursive comparison, for that you could use https://github.com/shazam/shazamcrest

Mocking method if one argument is raw and other may be from list

I want to test if method was invoked X times with one raw argument and other arguments from list. I found this method:
Mockito.verify(mock,Mockito.times(3)).myMethod(Mockito.eq("lastName"),
Mockito.argThat(Matchers.isOneOf("firstName","name","firstName"))));
However this complains that argThat method needs ArgumentMatcher but Matchers.isOneOf returns org.hamcrest.Matcher
Is there any other way that i could achieve this?
Thanks for help!
This changed in Mockito 2.1.0. On the Mockito web site, there is this migration advice.
All existing custom implementations of ArgumentMatcher will no longer
compile. All locations where hamcrest matchers are passed to argThat()
will no longer compile. There are 2 approaches to fix the problems:
a) Refactor the hamcrest matcher to Mockito matcher: Use implements
ArgumentMatcher instead of extends ArgumentMatcher. Then refactor
describeTo() method into toString() method.
b) Use org.mockito.hamcrest.MockitoHamcrest.argThat() instead of
Mockito.argThat(). Ensure that there is hamcrest dependency on
classpath (Mockito does not depend on hamcrest any more).
What option
is right for you? If you don't mind compile dependency to hamcrest
then option b) is probably right for you. Your choice should not have
big impact and is fully reversible - you can choose different option
in future (and refactor the code)

mockito : mock method call with parameters by reflection

I'm using mockito and developping with java6 and spring.
I'm working on a test API for some developpers and I propose a few methods for mocking objects and methods (it's a legacy code...).
Now, I want to replace all this things by mockito but I always propose a test API. So, I developped some methods using mockito.
I have an old method with two parameters (String). A first parameter is a mocked service id and its method with parameters. And the second parameter is the returned Object.
Example :
mockReturnObject("myServiceId.myMethod(String, Integer)", myReturnedObject);
Now, I want to use mock, when and thenReturn mockito methods, and I don't see how...
Perhaps with reflection but with "when" method it's impossible because mockito need the effective method.
How can I do that ? thanks.
This is a bad idea: you're trying to reimplement some of the systems Mockito already provides while losing out on many of the features Mockito offers. However, there is a way to make this work, with some difficulty. The key is to write a custom Answer, make it the default answer for the mock, and then compare your object, method name, and method parameter types using InvocationOnMock.
public class ReflectiveMockAnswer implements Answer<Object> {
#Override public Object answer(InvocationOnMock invocation) {
// Assume you've successfully parsed each String into a StubbedResponse, with
// Object target, String method, String[] argTypes, and Object returnValue.
// A Set would beat a for-loop here, should you need to optimize.
for (StubbedResponse stubbedResponse : allStubbedResponses) {
if (stubbedResponse.target == invocation.getMock()
&& stubbedResponse.method.equals(invocation.getMethod().getName())
&& stringArraysEqual(stubbedResponse.argTypes,
typeNamesFrom(invocation.getMethod().getParameterTypes())) {
return stubbedResponse.returnValue;
}
}
throw new RuntimeException("Unstubbed method called.");
}
}
// Later...
Object yourMockObject = Mockito.mock(classToMock, new ReflectiveMockAnswer());
At that point, you've implemented a simplified version of Mockito within and based on the full version of Mockito. You'll also need to:
Parse the string into a StubbedResponse, probably with regular expressions
Identify the field in your bean-under-test by name
Replace that field with a mock of the appropriate class, created as above, before the bean-under-test has a chance to interact with it
...and acknowledge that this solution doesn't handle:
Verification
Any sort of argument matching, including basic "equals" matching
Name collisions in parameter types (com.foo.SomeClass vs com.bar.SomeClass)
Repeated calls (thenReturn(1, 2, 3).thenThrow(new RuntimeException()))
...and cannot handle:
Code search tools: you can only tell which methods are mocked other than by searching for strings, not with tools like "Find references" in Eclipse the way Mockito can
Compile-time checking and automated refactoring tools: your tests would break at runtime if field names, method names, or parameters change; Mockito doesn't have that problem
Final methods: Mockito can't, so you can't either
Unless this is a "straw man" or very temporary solution, I recommend strongly to just introduce Mockito directly into your test cases, one test at a time.

Mocking of aggregates with any Java mocking framework

Are there any mocking framework that can do a "full" mocking of every child in an aggregate? For example.
final Report report = createMock(Report.class);
expect(report.getReportSides().get(0).getSideGroup().get(1)).andStubReturn(createSomething());
I want this call with these indices be mocked without me having to do anything else, and before I start to write some massive testing code... is this possible in any framework, EasyMock, PowerMock, Mockito, etc?
(The class example is a legacy class auto-generated from a customers XML, hence the weird class structure, and the absence of domain service layer).
I'm sure you know it's strongly advised to not mock values, but with legacy stuff there could be funky stuff.
Anyway the following declaration might do a great part of the job:
mock(Report.class, RETURNS_DEEP_STUBS)
However you seem to have collections in your aggregate report.getReportSides().get(0).getSideGroup().get(1), and due to type generics erasure Mockito or others frameworks cannot infer the runtime type that should be in the collections, so RETURNS_DEEP_STUBS answer will create a mock matching the return type that is read through reflection, and will certainly be a mock of Object itself in the case of java collections. So you'll have to deal with it manually.
As a side note, there have been progress for generic types in mockito trunk, it can retrieve more generic information that is embedded in the class, it's clearly not near anything that have runtime introspection (impossible with current versions of Java) but it gets closer to it.
With the upgraded RETURNS_DEEP_STUBS you could do :
public interface A<K extends MyKeyType> extends Map<K, MyValueType> {}
deepStubMock.entrySet().iterator().next()
.getValue().someValueTypeMethod().eventuallyFollowedByAnotherMethod();
EDIT : looks like David answered before me in the comment :)

Using Hamcrest matchers with JMock in Groovy

I'm new to Groovy (and to JMock too for that matter) and having some trouble building expectations that use matchers on the parameters of the methods being mocked. When I try to do something like this:
Expectations e = new Expectations();
e.allowing(mockObject).doSomething(Expectations.with(aNonNull(ImmutableCollection.class)))
e.will(returnValue(someResponse))
It causes the following error when building the expectation:
groovy.lang.MissingMethodException: No signature of method: static org.jmock.Expectations.with() is applicable for argument types: (org.hamcrest.core.IsNot) values: [not null]
Possible solutions: with(boolean), with(org.hamcrest.Matcher), with(byte), with(org.hamcrest.Matcher), with(char), with(org.hamcrest.Matcher)
aNonNull returns Matcher<T> (org.hamcrest.core.IsNot implements Matcher<T>) and there is an Expectations.with method that takes a Matcher so I'm not sure why Groovy is trying to find a version of with that takes the concrete class rather than the interface specified by aNonNull. I've also tried casting the return value of aNonNull to both Matcher and Matcher<T> without any change in the error. I'm not sure if there's something about the generics that's confusing Groovy or what else to check.
According to the JavaDoc, org.jmock.Expectations.with() is an instance rather than a static method. That's why you get an error.
By the way, testing/mocking frameworks built specifically for Groovy will make your life a lot easier (even when testing Java code). For example, the same expectation looks like this in Spock (http://spockframework.org):
mockObject.doSomething(_ as ImmutableCollection) >> someResponse
Another Groovy mocking framework to be aware of is GMock (http://code.google.com/p/gmock/).

Categories

Resources