I'm trying to mock the following piece of code in my JUnit test
requestData = requestRepository.findByRequestId(requestId);
by doing
#Mock
RequestRepository requestRepository;
#Mock
RequestData requestData;
Mockito.when(requestRepository.findByRequestId(requestId)).thenReturn(requestData);
But instead of giving the mock object back, i'm getting null value.
What is the correct way to mock MongoDB repository methods.
When using SpringRunner based test, use #MockBean to declare mock of your context beans.
If you don't know about your request id value (it may be a dynamic value) on that case you can use Mock.any(<?>.class).
Example:
Mockito.when(requestRepository.findByRequestId(Long.class)).thenReturn(requestData);
The above example is only for requestId of type Long, if you need integer then you need to change the class to Integer.
In EasyMock, when using annotation #Mock
You can set the to which member of the target object the mock will be assigned, using fieldName
Example:
/*assign mock impl ONLY for myInterface2 member of tested object*/
#Mock(type= MockType.NICE, name="secondMember", fieldName = "myInterface2")
private MyInterfaceImpl myInterfaceMock; //step 1 for runner
This is very convenient as I don't need to create a special constructor to assign the internal members with mocked objects
Question:
Is there such thing for partial mocking as well?
Many Thanks!
No. #Mock can't create partial mocks (yet). You can request it as a feature request: https://github.com/easymock/easymock/issues
How can you get a mock object in at runtime when it is not created/initialized in the class you are testing, it is not static (singleton pattern), or you don't have some sort of test constructor to hook into?
In a class that I am writing some unit testing for, I have come across a scenario I haven't encountered/solved yet. I have a JMS resource (a QueueConnectionFactory for reference, but it shouldn't matter), that is a private variable of the class I am testing. Since it has the javax.annotation.Resource annotation, at runtime it is assumed to be available. During testing, it is not, which creates the need for mocking this object.
It is not a static class and is not being used in a static way, if it was I could easily mock using the various static mocking methods I have run into. Since the resource is never created locally (in a constructor or even in a test constructor), I have no way of passing in a Mock object so that at runtime of the test, the mock is used instead of the actual object. How can I mock this Resource so that when the test executes, it will be used in place of the private #Resource object in the class I am testing?
For reference, the code is calling createConnection() on the QueueConnectionFactory which is throwing a null pointer exception since the Factory has not been initialized/mocked.
#Stateless
public class Example{
#Resource(name = "jms/exampleQCF")
private QueueConnectionFactory queueFactory;
...
public void testMe(){
Connection connection = queueFactory.createConnection();
...
}
}
After a lot more hunting around and looking at all the options Mockito/Powermock had to offer, I found the solution (which I will share in case others run into this same issue).
When you have private member variables that are never initialized (and just assumed created in other places), you can use the #InjectMocks annotation to "inject" Mocks you want into your class you are testing.
Add a variable in your test class for the class you are testing, and give it the annotation #InjectMocks (org.Mockito.InjectMocks).
Use #Mock annotations to setup the mocks you want to inject. Use the #Mock (name = "privateVariableNameHere") name property to map the Mock object to the private variable inside your class you are testing.
In either a setup function or before you call your class, initialize the mocks. The easiest way I have found is to use a "setup" method with the #Before annotation. Then inside there call MockitoAnnotations.initMocks(this); to quickly initialize anything with the #Mock annotation.
Define your Mock functionality in your test method (before calling the method you are testing).
Using the #InjectMock object, call your method you are testing... the mocks SHOULD be hooked in and working as defined in the earlier steps.
So for the example class I use above, the code to test/mock would have Connection returned as a mock which you can do whatever with. Based on the example above in my question, this is what the code would look like:
#RunWith(PowerMockRunner.class)
#PrepareForTest({/* Static Classes I am Mocking */})
public class ExampleTest {
#Mock (name = "queueFactory") //same name as private var.
QueueConnectionFactory queueFactoryMock;
#Mock
Connection connectionMock; //the object we want returned
#InjectMocks
Example exampleTester; //the class to test
#Before
public void setup(){
MockitoAnnotations.initMocks(this); // initialize all the #Mock objects
// Setup other Static Mocks
}
#Test
public void testTestMe(){
//Mock your objects like other "normally" mocked objects
PowerMockito.when(queueFactoryMock.createConnection()).thenReturn(connectionMock);
//...Mock ConnectionMock functionality...
exampleTester.testMe();
}
}
Several approaches here:
ReflectionTestUtils of Spring Testing framework: ReflectionTestUtils.setField(objectToTest, "privateFieldName", mockObjectToInject);. With this you don't introduce another dependency.
org.mockito.internal.util.reflection.FieldSetter.
PowerMock.Whitebox.setInternalState() to mock a private field.
If you need to mock internal local variable creation, use PowerMockito.whenNew(Foo.class).withNoArguments().thenReturn(foo);. Very, very useful. Cannot find other ways to do the same.
With only Mockito you cannot mock local variable creation, because when(any(Foo.class) does not work; will return null. It compiles but does not work.
References:
Mockito: Mock private field initialization
I have implemented a Java EE page which connects to an inventory webservice. I have implemented an inventory controller as shown below:
public class InventoryController {
#Autowired
private WebServiceTemplate inventoryWsTemplate;
...
}
inventoryWsTemplate is declared as a bean in web-servlet.xml.
The program works but I'm getting a warning that says:
field is used but is never assigned a non-"null" value
What should I do?
Just add a SuppressWarnings annotation:
#Autowired
#SuppressWarnings("null")
private WebServiceTemplate inventoryWsTemplate;
Normally I'd add a comment to justify the annotation (e.g. // Used by guice) but in this case coming hot on the heels of an Autowired annotation, I don't think it's necessary.
EDIT: I can't reproduce the problem on Eclipse to start with, so I'm not sure which annotation value is required. You should check the list of supported annotation values for your compiler.
If you don't like suppressing warnings, you can change private to any other access modifier. Package-private probably being the best choice (besides private).
I have a very simple test case that is using Mockito and Spring Test framework. When I do
when(pcUserService.read("1")).thenReturn(pcUser);
I get this exception.
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.
2. inside when() you don't call method on mock but on some other object.
at com.project.cleaner.controller.test.PcUserControllerTest.shouldGetPcUser(PcUserControllerTest.java:93)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
I have tried with different methods but keep on getting this error message. I am using Spring 3.1.0.RELEASE with Mockito. Please share and guide me in the right direction.
You need to create a MOCK of pcUserService first, and then use that mock.
PcUserService mock = org.mockito.Mockito.mock(PcUserService.class);
when(mock.read("1")).thenReturn(pcUser);
In case others hit this issue....
It could also be the case that the method you are trying to mock out,pcUserService.read, is declared as a final method. From what I've noticed this appears to cause issues with Mockito.
If you use Kotlin, you should know that methods are final by default. So write open fun instead of fun. Thanks to #djkelly99 for a tip.
Another solution to this issue might be that in case of a test class that is using PowerMockRunner, you might have to add the class that you are mocking to the list, in #PrepareForTest annotation.
For instance -
#PrepareForTest({ PcUserService.class })
In my case it was solved by injecting #MockBean.
For ex.
#MockBean
StateRepository mockStateRepository;
There's another possible reason for such error - sometimes IDE prefers to statically import Mockito.when() from another package:
import static io.codearte.catchexception.shade.mockito.Mockito.when;
vs
import static org.mockito.Mockito.when; //should normally use this one
The thing is 'when' from io.codearte package is compliant with org.mockito.Mockito.any() on compilation level, but fails during runtime with that exact same error message.
I had the same issue, the method that I was trying to mock it was a final method. I removed the modifier and it worked fine.
For the help of others who stuck with the same problem;
The method you are trying to mock , pcUserService.read, is declared as a final method. Static methods appears to cause issues with Mockito.
If you get this exception when using MockedStatic or Mockito.mockStatic, it can also mean that you are mixing matchers and literals in the call to the static method.
Try changing any mixes like YourClass.staticMethod(any(), "literal") to YourClass.staticMethod(any(), eq("literal"))
Basically You need to use the PowerMockito.mockStatic to enable static mocking for all static methods of a class. This means make it possible to stub them using the when-thenReturn syntax.
For example:
PowerMockito.mockStatic(TestClass.class);
when(TestClass.getString()).thenReturn("HelloWorld!");
Note: you have to add #PrepareForTest({ TestClass.class }) to your unit test class.
If you use KOIN, include in the gradle's dependencies:
dependencies {
...
testImplementation "org.koin:koin-test:2.0.0"
}
I faced similar issue when mocking static method of anotherClass called inside testing a method of someClass. In that case, we need to add #PrepareForTest({anotherClass.class, someClass.class}) both the class having the static method and caller class.
When I got this exception, I was using #InjectMocks on the class that I needed to have the #Mock objects injected into (via constructor injection).
AFter much searching, I finally stumbled across this article:
https://mkyong.com/spring-boot/mockito-when-requires-an-argument-which-has-to-be-a-method-call-on-a-mock/
The key part to take away from it is (from the article):
When Mockito see this #InjectMocks, it doesn’t mock it, it just
creates a normal instance, so the when() will be failed.
So this make this exception message I was getting
when() requires an argument which has to be 'a method call on a mock'.
make sense now; you aren't using when on an actual mock but an actual instance.
The link also provides the solution to the problem:
To solve it, annotate #Spy to mock it partially.
On top of #InjectMocks, put #Spy.
As a side note, if you try to make it a Mock by putting #Mock on top of #InjectMocks, you will get exception:
org.mockito.exceptions.base.MockitoException: This combination of
annotations is not permitted on a single field: #Mock and #InjectMocks
Using #Spy on top of #InjectMocks solved the problem for me.
I faced same issue and it was because the mocked object is defined as #Beanand the overriden #Bean in the test was not working because of a missing spring property value
#Bean
#Primary
public JwtTokenUtil jwtTokenUtil() {
return Mockito.mock(JwtTokenUtil.class);
}
#Autowired
private JwtTokenUtil jwtTokenUtil;
when(jwtTokenUtil.validateToken(jwtToken)).thenReturn(true);
Fix
spring.main.allow-bean-definition-overriding=true in application-test.properties
if anything above answers your case, then check that you did missed the #Test annotation for your test method.
#Test
public void my_test_method(){
}
just quoting, as this was my case. just missed the annotation.