Mockito mock objects returns null - java

I try to implement some tests for my JSF application and for the mocks I am using mockito. (I also use spring)
#RunWith(MockitoJUnitRunner.class)
public class GeneralConfigServiceImplTest {
private GeneralConfigService generalConfigService;
#Mock
private GeneralConfigDAO generalConfigDAO;
#Mock
private GeneralConfig gen;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
generalConfigService = new GeneralConfigService();
ReflectionTestUtils.setField(generalConfigService, "generalConfigDAO", generalConfigDAO);
}
#Test
public void testAddGeneralConfigCallDAOSuccess() throws DAOException, EntityNullException, IllegalEntityArgumentException, ParseException, EntityPersistException {
gen = createGeneralConfigs("label", "value");
generalConfigService.setInstance(gen);
generalConfigService.persist();
log.info(generalConfigService.getInstance().toString());
}
}
The test succeeds, but when I want to retrieve the instance with the getInstance method. All Parameters which I have set before (via the constructor before) are null.
I am new to mocked objects, so is this behavior normal, or is there a mistake in my code?

It really depends on GeneralConfigService#getInstance() implementation. Also you can simplify your test code a lot if you use #InjectMocks annotation.
When using MockitoJUnitRunner you don't need to initialize mocks and inject your dependencies manually:
#RunWith(MockitoJUnitRunner.class)
public class GeneralConfigServiceImplTest {
#InjectMocks
private GeneralConfigService generalConfigService;
#Mock
private GeneralConfigDAO generalConfigDAO;
#Test
public void testAddGeneralConfigCallDAOSuccess() {
// generalConfigService is already instantiated and populated with dependencies here
...
}
}

My problem here was the incorrect import for Test anotation:
Was
import org.junit.jupiter.api.Test;
Correct
import org.junit.Test;

Don't forget to use
MockitoAnnotations.initMocks(this);
If you are Mocking object through annotation i.e. #Mock Objectname

All method calls to Mockito mocks return null by default. If you want it to return something else you need to tell it to do so via a when statement.
It seems the you are thinking that the following will work... you call setInstance and then expect getInstance to return the value that was passed to setInstance since this is how the DAO would work. If this is what you are attempting, you shouldn't test setInstance by then calling getInstance since getInstance will return whatever you have configured the mock to return and will have no relation to what was passed to setInstance. Instead, use verify to validate that the appropriate method of the DAO was called from the setInstance method.
For example, if GeneralConfigService.setInstance calls GeneralConfigDAO.setInstance then your test should look like this...
#Test
public void testAddGeneralConfigCallDAOSuccess() throws DAOException, EntityNullException, IllegalEntityArgumentException, ParseException, EntityPersistException {
gen = createGeneralConfigs("label", "value");
generalConfigService.setInstance(gen);
generalConfigService.persist();
verify(genConfigDAO).setInstance(sameInstance(gen));
}
Also, if gen is a mock (via #Mock) why are you assigning it to something else via gen = createGeneralConfigs...

This thread is an old one, but I got the same problem with junit5 (v5.8.2) and mockito (mockito-core:jar:4.5.1) and none of the answers here helped me. After a 1.5 hours search I found this article:
https://mincong.io/2020/04/19/mockito-junit5/
which helped me! I used the first solution, so I added
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.28.2</version>
<scope>test</scope>
</dependency>
as new dependency and I annotated my class with the following annotation (and I removed the #RunWith(MockitoJUnitRunner.class) annotation):
#ExtendWith(MockitoExtension.class)
Please find the explanation in the article. I hope this help to others as well!

Related

JUnit for final method of abstract class

I am having trouble writing a JUnit test. The issue is that there is a final method getMessage() in the following block of code:
if(these_conditions_are_true) {
String message = messageResources.getMessage(CONSTANT_STRING, null, LocaleContextHolder.getLocale());
modelView.getModelMap().addAttribute(INLINE_MSG, message);
return modelView;
}
messsageResources is a ReloadableResourceBundleMessageSource which extends AbstractMessageSource, which is an abstract class.
getMessage() is a final method in AbstractMessageSource.
Here is the condensed version of my Test class:
#RunWith(PowerMockRunner.class)
#PrepareForTest({AbstractMessageSource.class, ClassBeingTested.class})
public class ClassBeingTestedTest {
#InjectMocks
ClassBeingTested classBeingTested;
#Mock
ReloadableResourceBundleMessageSource messageResources; //being used by a different test in this class, including in case it matters
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
// Build the mock
this.mockMvc = MockMvcBuilders.standaloneSetup(classBeingTested).build();
}
#Test
public void Method_Being_Tested_Test() {
AbstractMessageSource amsMock = PowerMockito.mock(AbstractMessageSource.class);
Mockito.when(amsMock.getMessage(any(), any(), any())).thenReturn("test01");
ModelAndView mv = classBeingTested.methodBeingTested(itemVO);
ModelAndView mv_Expected = createExpectedMV(); //not really how i'm doing it, but for the sake of simplicity i'll omit it
assertEquals(mv_Expected, mv);
}
}
I'm using PowerMockito since I learned that Mockito can't stub final methods.
The error I get is
No message found under code 'CONSTANT_STRING' for locale 'EN_US'.
It appears that my when...thenReturn isn't actually being used as getMessage() is being called. I've tried adding CALLS_REAL_METHOD to the line where I create the Mock, but that didn't seem to work.
Does anyone know how to stub this out? Am I right to mock AbstractMessageSource, rather than ReloadableResourceBundleMessageSource? Any help would be greatly appreciated!
UPDATE:
I'm still looking for help with this. I'm still running into the issue of not being able to intercept getMessage() actually being called...
Try this
Mockito.when(
amsMock.getMessage(
eq(CONSTANT_STRING),
eq(null),
any(Locale.class))).thenReturn("test01");
Edit: This strategy is terrible,
because you will need to mock the getMessage method for every property that is accessed during your unit test.
What you appear to want is the ability to set a property value for use during your unit tests.
If this is the case,
include a property configuration for your unit tests.
For spring,
you can create a unit test configuration that references the test properties and load it with the SpringRunner.

Null after #InjectMocks

I am having some troubles passing a dependency while unit testing with JUnit.
Consider these pieces of code:
This is the dependacy injecton into the class which i want to test, lets call it Controller.
#Inject private FastPowering fastPowering;
And this is the unit test:
#RunWith(MockitoJUnitRunner.class)
public class ControllerTest {
#Mock
FastPowering fastPower;
#InjectMocks
Controller controller;
#Test
public void test() {
assertEquals(
(controller.computeAnswer(new BigDecimal(2), 2)).longValue(),
(long) Math.pow(2, 2));
}
}
It seems that fastPower is null, please explain how to fix that.
Null pointer exception , because of calling the #injected field (fastPower) inside the .computeAnswer method)
Edit:
Solved i should have read about the difference between #Mock and #Spy...
Due to a lot of comments I am adding some more context to the solution
The difference is that in mock, you are creating a complete mock or fake object while in spy, there is the real object and you just spying or stubbing specific methods of it. While in spy objects, of course, since it is a real method, when you are not stubbing the method, then it will call the real method behavior.
If fastPower is annotated as #Mock it's methods are dummy, yet controller.computeAnswer depends on them to compute. One must provide behaviour.
If spy is used without stubbing then the real implementation of fastPower is being executed which eventually returns desired value.
Another option is to use a real FastPowering instance
https://github.com/mockito/mockito/wiki/Using-Spies-(and-Fakes)
https://github.com/mockito/mockito/wiki/Mocking-Object-Creation
And some stackoverflow thread outlining the difference Mocking vs. Spying in mocking frameworks
Short Answer: Replace #Mock with #Spy and should be working fine
Use MockitoAnnotations.initMocks to initiate the #Mock and #InjectMocks objects. Your test would look something like:
#Mock
FastPowering fastPower;
#InjectMocks
Controller controller;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
....
}
After debugging I found a reason. This is because of the org.powermock.core.MockRepository#instanceMocks collection. It doesn't contain a mock for a field with #InjectMocks annotation (Controller controller in your case).
To solve it try to use the #Spy annotation in the field declaration with initializing of them and #PrepareForTest above the class declaration:
#PrepareForTest(Controller.class)
#RunWith(MockitoJUnitRunner.class)
public class ControllerTest {
#Mock
FastPowering fastPower;
#Spy
#InjectMocks
Controller controller = new Controller();
#Test
public void test() {
//...
}
}
In my case it helped. Using of the Mockitoannotations.initMocks(this) method is not required, it doesn't affect the result.
I fixed this by removing the extraneous new instance I was creating in my #Before method (see example below). It was also fixed by moving MockitoAnnotations.initMocks(this) after initializing myClass, but since Mockito created myClass anyway, that solution was inferior.
// Note - you may need #mock(name="foo") to help mockito differentiate props
// if they have the same type
#mock
private Thing something;
#InjectMocks
private MyClass myClass;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this); // Moving this below the next line fixed it...
myClass = new MyClass() // But just remove this line and let Mockito do the work
}
Useful to note that the use of MockitoAnnotations.initMocks(this); needs to come at the end of your #Before/setUp() method.
If it is at the top of your setUp() then it may cause other mocked classes to not be initialised.
I ran into this error myself just now and placing .initMocks at the end of my #Before solved my issue.
I was using the wrong #Test annotations, If you want to use #InjectMocks and #Mock in your Mockito Test, then you should
add #ExtendWith(MockitoExtension.class) annotation on your test class
annotate your test methods with #Test (org.junit.jupiter.api.Test) and not the #Test (org.junit.Test) annotation. be careful with the import that you are using for this annotation.
This works on mockito-core:3.6.28
2 more things to check:
1. Mocking the behaviours of fastPower. What should this mocked object return, when it methods are called? i.e. when(fastPower.doSomething()).thenReturn(some_kind_of_object);
2. Check if the controller.computeAnswer() does not return NULL for the input of new BigDecimal(2), 2)).longValue(), (long) Math.pow(2, 2).

How to mock another method in the same class which is being tested?

I am writing JUnit Test case for a class which has two methods methodA,methodB.
I would like to mock the call to the methodB from methodA in my test case
I am using spy on the class which I am testing, but still the methodB gets executed.
here is the class
public class SomeClass
{
public Object methodA(Object object)
{
object=methodB(object);
return object;
}
public Object methodB(Object object)
{
//do somthing
return object;
}
}
here is the test class
#RunWith( org.powermock.modules.junit4.legacy.PowerMockRunner.class )
#PrepareForTest(SomeClass.class)
public class SomeClassTest {
private SomeClass var = null;
#Before
public void setUp() {
var=new SomeClass();
}
#After
public void tearDown()
{
var= null;
}
#Test
public void testMethodA_1()
throws Exception {
Object object =new Object();
SomeClass spy_var=PowerMockito.spy(var);
PowerMockito.when(spy_var.methodB(object)).thenReturn(object);
Object result = var.methodA(object);
assertNotNull(result);
}
}
The method B still gets the called though I have mocked it
PLease suggest me a solution with the proper way of mocking the methodB call from methodA of the same class.
I ran into this yesterday, for spies is best to do:
doReturn(X).when(spy).method(any())
Taking this approach will result in brittle tests which will need to change if you refactor your class under test. I would highly recommend that you try to assert your expected test results by checking state of SomeClass rather than relying on mocks.
If you do indeed need to mock MethodB then this is an indication that maybe the behaviour in MethodB actually belongs in a separate class which you could then test the interaction of SomeClass with via mocks
if you do indeed need to do what you ask for then a PartialMock is what you want.
you probably want to create a partial mock of some class but indicate that calls to MethodA should call the actual method but then mock MethodB
You can see how to use them in the Mockito documentation
As stated in their documentation though Partial mocks are a code smell, though they have identified some explicit use cases.
As per #Totoro's answer, this is just a summary here.
Annotate the object for the class you are testing with the #Spy annotation.
So this:
#Spy
#InjectMocks
MyClassUnderTest myClassUnderTest;
instead of just
#InjectMocks
MyClassUnderTest myClassUnderTest;
Use doReturn() instead of when.thenReturn() whenever asking for the mocked object from the class spyed on (class under test).
doReturn(X).when(myClassUnderTest).method(any())
I had this very same challenge. Have a look at this solution which will work for newer testing suit versions.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>2.5.0</version>
</dependency>
Solution-
//when- then for MethodA test
SomeClass spy_var=Mockito.spy(var);
doReturn(X).when(spy_var).methodB(object)
Object result = spy_var.methodA(object);
//assertions on result

Java: How do I mock a method of a field when that field isn't exposed?

I'm using Java 6, JUnit 4.8.1, and writing a console application. My application has a member field that isn't exposed …
public class MyApp {
...
private OpportunitiesService m_oppsSvc;
private void initServices() {
…
m_oppsSvc = new OpportunitiesServiceImpl(…);
}
...
}
I want to mock a behavior such that whenever one method from my service is called, (e.g. m_oppsSvc.getResults()), the same result is always returned. How do I do that? There's no setter method for the field. I'm currently working with Mockito 1.8.4. Is it possible to do this with Mockito or some other mock framework?
This is what you want:
#RunWith(MockitoJUnitRunner.class)
public class MyAppTest {
#Mock private OpportunitiesService mocked_m_oppsSvc;
#InjectMocks MyApp myApp;
#Test public void when_MyApp_uses_OpportunititesService_then_verify_something() {
// given
given( mocked_m_oppsSvc.whatever()).willReturn(...);
// when
myApp.isUsingTheOpportunitiesService(...);
// then
verify...
assertThat...
}
}
Using: Mockito 1.9.0, BDD style, FEST-Assert AssertJ.
Hope that helps :)
Given that you're already using mockito, why not just use reflection:
#RunWith(MockitoJUnitRunner.class)
public class MyApp {
#Mock
private OpportunitiesService m_oppsSvc;
private MyApp myApp;
#Before
public void before() throws Exception {
myApp = new MyApp();
Field f = MyApp.class.getDeclaredField("m_oppsSvc");
f.setAccessible(true);
f.set(myApp, m_oppsSvc);
}
}
It's a bit ugly, but it will do the trick. Note that this may not be the most efficient way to do it with Mockito, but it will work.
There's also Powermock which should allow you to do this as well using the Whitebox class. I won't get into the whole details of Powermock but here's the call to inject the private field value, which should be a mock object:
Whitebox.setInternalState(myApp, "m_oppsSvc", m_oppsSvc);
You should consider attempts to mock a private field a smell. That is, a sign that either what you're trying to do is either incorrect or that your code is currently structured incorrectly. You should only need to mock public methods or injected dependencies
In the code you've given you should consider injecting OpportunitiesService as follows:
public class MyApp {
...
private OpportunitiesService m_oppsSvc;
public MyApp(OpportunitiesService oppsSvc) {
this.m_oppsSvc = oppsSvc;
}
...
}
In your test you can then inject a mock as follows:
OpportunitiesService mockOpportunitiesService =
Mockito.mock(OpportunitiesService.class);
Mockit.when(mockOpportunitiesService.someMethod()).thenReturn(someValue);
MyApp app = new MyApp(mockOpportunitiesService);
You can easily do it with JMockit:
public class MyAppTest
{
#Tested MyApp myApp;
#Test
public testSomething(final #Capturing OpportunitiesService mockService)
{
new NonStrictExpectations() {{
mockService.getResults(); result = asList("a", "b", "C");
// record other expectations, if needed
}};
myApp.whateverMethodIWantToTest();
new Verifications() {{
mockService.doSomething(anyInt);
// verify other expectations, if needed
}};
}
}
Even though the implementation class OpportunitiesServiceImpl isn't mentioned in test code, its instances (any number of them) will still get properly mocked.
Generally you should use dependency injection and pass the mock object (of type OppportunitiesServiceImpl) in via the constructor, a separate setter or directly to the method (getResults). You might need to extract an interface for OpportunitiesServiceImpl first.
Usually, this is solved through the use of dependency injection. In regular (production) mode, your dependency injection container (e.g. Spring or Guice) will inject an instance of OpportunitiesService into MyApp through your constructor or through a setter.
Then, when you're testing you can "inject" a mock instance manually using the same setter or constructor argument.
Instead of doing
m_oppsSvc = new OpportunitiesServiceImpl(…);
Try Passing OpportunitesService in through MyApp's constructor

Mockito, Testing an object that relies on injected dependencies (Spring)?

I'm new to using Mockito and am trying to understand a way to make a unit test of a class that relies on injected dependencies. What I want to do is to create mock objects of the dependencies and make the class that I am testing use those instead of the regular injected dependencies that would be injected by Spring. I have been reading tutorials but am a bit confused on how to do this.
I have one the class I want to test like this:
package org.rd.server.beans;
import org.springframework.beans.factory.annotation.Autowired;
public class TestBean1 {
#Autowired
private SubBean1 subBean1;
private String helloString;
public String testReturn () {
subBean1.setSomething("its working");
String something = subBean1.getSomething();
helloString = "Hello...... " + something;
return helloString;
}
Then I have the class that I want to use as a mock object (rather than the regular SubBean1 class, like below:
package org.rd.server.beans.mock;
public class SubBean1Mock {
private String something;
public String getSomething() {
return something;
}
public void setSomething(String something) {
this.something = something;
}
}
}
I just want to try running a simple test like this:
package test.rd.beans;
import org.rd.server.beans.TestBean1;
import junit.framework.*;
public class TestBean1Test extends TestCase
{
private TestBean1 testBean1;
public TestBean1Test(String name)
{
super(name);
}
public void setUp()
{
testBean1 = new TestBean1();
// Somehow inject the mock dependency SubBean1Mock ???
}
public void test1() {
assertEquals(testBean1.testReturn(),"working");
}
}
I figure there must be some fairly simple way to do this but I can't seem to understand the tutorials as I don't have the context yet to understand everything they are doing / explaining. If anyone could shed some light on this I would appreciate it.
If you're using Mockito you create mocks by calling Mockito's static mock method. You can then just pass in the mock to the class you're trying to test. Your setup method would look something like this:
testBean1 = new TestBean1();
SubBean1 subBeanMock = mock(SubBean1.class);
testBean1.setSubBean(subBeanMock);
You can then add the appropriate behavior to your mock objects for whatever you're trying to test with Mockito's static when method, for example:
when(subBeanMock.getSomething()).thenReturn("its working");
In Mockito you aren't really going to create new "mock" implementations, but rather you are going to mock out the methods on the interface of the injected dependency by telling Mockito what to return when the method is called.
I wrote a test of a Spring MVC Controller using Mockito and treated it just like any other java class. I was able to mock out the various other Spring beans I had and inject those using Spring's ReflectionTestUtils to pass in the Mockito based values. I wrote about it in my blog back in February. It has the full source for the test class and most of the source from the controller, so it's probably too long to put the contents here.
http://digitaljoel.nerd-herders.com/2011/02/05/mock-testing-spring-mvc-controller/
I stumbled on this thread while trying to set up some mocks for a slightly more complicated situation and figured I'd share my results for posterity.
My situation was similar in the fact that I needed to mock dependencies, but I also wanted to mock some of the methods on the class I was testing. This was the solution:
#MockBean
DependentService mockDependentService
ControllerToTest controllerToTest
#BeforeEach
public void setup() {
mockDependentService = mock(DependentService.class);
controllerToTest = mock(ControllerToTest.class);
ReflectionTestUtils.setField(controllerToTest, "dependantService", mockDependentService);
}
#Test
void test() {
//set up test and other mocks
//be sure to implement the below code that will call the real method that you are wanting to test
when(controllerToTest.methodToTest()).thenCallRealMethod();
//assertions
}
Note that "dependantService" needs to match whatever you have named the instance of the service on your controller. If that doesn't match the reflection will not find it and inject the mock for you.
This approach allows all the methods on the controller to be mocked by default, then you can specifically call out which method you want to use the real one. Then use the reflection to set any dependencies needed with the respective mock objects.
Hope this helps someone down the road as it stumped me for a while.

Categories

Resources