how to match the String... use Mockito and PowerMock - mockito

I am studying Mockito and PowerMock recently.
I ran into the following problem
//This method belongs to the Messages class
public static String get(Locale locale, String key, String... args) {
return MessageSupplier.getMessage(locale, key, args);
}
//the new class
#RunWith(PowerMockRunner.class)
#PowerMockIgnore( {"javax.management.*"})
#PrepareForTest({Messages.class, LocaleContextHolder.class})
public class DiscreT {
#Test
public void foo() {
PowerMockito.mockStatic(LocaleContextHolder.class);
when(LocaleContextHolder.getLocale()).thenReturn(Locale.ENGLISH);
PowerMockito.mockStatic(Messages.class);
when(Messages.get(Mockito.any(Locale.class),Mockito.anyString(), Mockito.any(String[].class)))
.thenReturn("123156458");
System.out.print(Messages.get(LocaleContextHolder.getLocale(), "p1"));
System.out.print(Messages.get(LocaleContextHolder.getLocale(), "p1", "p2"));
}
}
the result : null 123156458
why? and how to match the String...

In your first System.out.print statement, you use 2 arguments for the Messages.get method. This is one of the method's overloads that you have not mocked. That's why it returns null. Note that object mocks that have not had their behavior mocked will return null by default.
You would have to mock the Messages.get(Locale, String) method as well if you want it to work
when(Messages.get(Mockito.any(Locale.class),Mockito.anyString()))
.thenReturn("123156458");
Remember, the fact that you have mocked the method that takes the most arguments doesn't mean Mockito understands and mocks the rest of the overloads! You have to mock them as well.
There is no way to mock a method once and automatically mock all of its overloads as far as I know however, there is a way to create a mock object and configure a default response for all of its methods. Check out http://www.baeldung.com/mockito-mock-methods#answer

Related

Issue with Mockito.Any for overloaded methods

I have two methods in my Java class as below
Method 1:
public ResponseEntity<T> callMethod(String param1,Map<String, String> param2, Object param3,HttpMethod param4,Class<T> param5)
Method 2
public ResponseEntity<T> callMethod(Map<String, String> param1, Object param2,
HttpMethod param3, Map<String, ?> param4,
final Class<T> param5) {
I have written a unit test case where when i try to call the method as below
callMethod(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any(),
eq(ServiceResponse.class))).thenReturn(responseEntity)
it fails with the below error
reference to callMethod is ambiguous
both method callMethod
(java.util.Map<java.lang.String,java.lang.String>,B,org.springframework.http.HttpMethod,java.util.Map<java.lang.String,?>,java.lang.Class)
and method
callMethod(java.lang.String,java.util.Map<java.lang.String,java.lang.String>,B,org.springframework.http.HttpMethod,java.lang.Class)
match
How can this be resolved. There are many unit test cases and i want to fix the class than the unit test cases. Is there a way?
Yes, you can put types in the any() like any(MyClass.class) there are also some built in ones. If you want to call your first method you can use the anyString() and anyMap() ones.
callMethod(Mockito.anyString(), Mockito.anyMap(), Mockito.any(), Mockito.any(HttpMethod.class), eq(ServiceResponse.class))).thenReturn(responseEntity)

Mockito: Intercept any methods that return a type

I've an interface like this:
public interface ICustomer extends IEnd<Customer> {
String getId();
ICustomer id(String id);
ICustomer email(String email);
ICustomer description(String description);
}
I need to mock any methods which returns an ICustomer regardless of parameters.
When these methods are called, the self called ICustomer have to be returned.
Any ideas?
To do this you need a custom Answer class:
public class CustomerAnswer implements Answer {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Class retType = invocation.getMethod().getReturnType();
if (ICustomer.class.isInstance(retType)) {
return invocation.getMock();
}
// provide default logic here -- override with "when()" calls.
return null;
}
}
Then create your mock, specifying the default behavior:
Foo mockCustomer = mock(ICustomer.class, new CustomerAnswer());
Add, when() statements for other methods that need to be stubbed.
But as I commented in the OP, be sure you actually want to mock this class before you go thru all the trouble. Only mock when it will make the test code simpler. If you have some simple implementation of the interface that is just a POJO with fluent API (no side-effects, no complicated dependencies or injections), there is probably no need to mock it. Instead use a real instance, because the real instance already returns the original object.
If you need to verify() on the ICustomer object, then use a #Spy of a real instance of a ICustomer.

Mocking static class in Mockito

I have something like the following:
public class Foo {
public static String getValue(String key) {
return key + "_" + System.currentTimeMillis();
}
}
Now I need to have a test case for it and here is how I attempted:
#Test
public void testFoo() {
PowerMockito.mockStatic(Foo.class);
PowerMockito.when(Foo.getValue("123")).thenReturn("abcd");
PowerMockito.verifyStatic();
}
When I run the test case, I get this:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
Those methods *cannot* be stubbed/verified.
Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.
at org.powermock.api.mockito.PowerMockito.when(PowerMockito.java:495)
Am I doing anything wrong?
Please advise.
Can you confirm that you've added a #PrepareForTest(Foo.class) annotation onto your test class as listed on the PowerMock site, and that you're using the PowerMockRunner JUnit4 runner?
Static methods are invoked with static dispatch, not dynamic dispatch using Java's normal polymorphism and method overrides. To replace the implementation, PowerMock needs to load a replacement class before the test starts running, and the runner and annotation make that happen.

Mock Void type in Mockito

Say Foo is the class we mock and Foo has a method named Foo.bar() which returns type Void (not void). How can we use Mockito to mock this method?
Not sure whether returning null in this case would be the best solution.
Because Void is final and not instantiable, there is no instance you could ever return. In production, that method can only return null (if it returns at all), and that should hold true in your tests as well.
Note that Mockito will return null by default for methods that return Object instances other than collections and primitive wrappers, so you should only need to stub a method that returns Void if you need to override a spied method:
// Spy would have thrown exception
// or changed object state
doReturn(null).when(yourSpy).someMethodThatReturnsVoid();
Or throw an exception:
// Throw instead of returning null by default
when(yourMock.someMethodThatReturnsVoid()).thenThrow(new RuntimeException());
Or react with an Answer:
when(yourMock.someMethodThatReturnsVoid()).thenAnswer(new Answer<Void>() {
#Override public void answer(InvocationOnMock invocation) {
// perform some action here
return null;
}
}

Caused InvalidUseOfMatchersException for clearly mocked class

I got error while running JUnit test with Mockito's matcher
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 1 recorded.
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
Here is source code.
class A
{
public String getField()
{
return "hi";
}
}
#Test
public void testA()
{
final A a = mock(A.class);
when(a.getField()).thenReturn(Matchers.any(String.class));
a.getField();
}
What is problem here? Please open my eyes!
You are using an argument matcher: Matchers.any(String.class). An argument matcher is not intended to be used as a return a value of a stubbed method.
An argument matcher should be used when you need to customize the way a method is stubbed :
when(a.sayHello(Matchers.any(String.class))).thenReturn("Hello");
In your example, you must return an instance of String and not a matcher :
when(a.getField()).thenReturn("theFieldValue");
You have made the classic error of mocking the class that you're trying to test. The whole point of mocking is that you remove other classes from consideration by your test. So if you're testing a class A that uses an object of class B in some way, you might make a mock of class B. But you wouldn't mock the class that you're actually testing, because then you are no longer testing the class, but testing the mocking framework.
In order to test the method you've supplied, it doesn't make sense to use Mockito at all; because there's no additional class that you want to remove from consideration by your test. The only class is A - the one you're testing.
Your test should just be the following
public class TestA {
private A toTest = new A();
#Test
public void getFieldReturnsHi() {
assertEquals("Hi", toTest.getField());
}
}

Resources