Hello i am new in Junit mockito i am trying to write a unit test
case but when i am run the test case i am getting null pointer
exception.
Code Snip:
package com.dataguise.webservices;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.*;
import com.dataguise.cache.CacheManager;
import com.dataguise.controller.CentralController;
import com.dataguise.webservices.beans.DgUserAuthorities;
class RestAPIsTest {
#InjectMocks
private CentralController controller;
#Mock
DgUserAuthorities dgUserAuthorities;
#Mock
private CacheManager cacheManager;
#BeforeEach
public void setup() {
when(this.cacheManager.getCache(anyString())).thenReturn(true);
MockitoAnnotations.initMocks(this);
}
#Test
void testSession() {
try {
dgUserAuthorities = controller.login("d", "d", "", false);
when(controller.login("d", "d", "", false)).thenReturn(dgUserAuthorities);
assertEquals(dgUserAuthorities, dgUserAuthorities);
} catch (Exception e) {
e.printStackTrace();
}
}
}
While the same method call in the rest api gives the appropriate result.
There are 2 errors in your test
Error 1: Mixing JUnit4 and JUnit5 annotations
org.junit.jupiter.api.Test is from JUnit 5
org.junit.Before is from JUnit 4
Thus, your #Before method is never executed. Use org.junit.jupiter.api.BeforeEach instead
Error 2: Using Spring annotations without Spring Extension
#Autowired comes from Spring's DI framework. It will be injected only if you use Spring Injection/ runner
If you want MockitoAnnotations.initMocks(this); to build object under test and inject all mocks, use #InjectMocks
Error 3: confusing way of initializing mocks
There are 2 ways to initialize your mocks:
Manually:
this.dgUserAuthorities = mock(DgUserAuthorities.class);
this.controller = new CentralController(this.dgUserAuthorities);
Using annotations
#InjectMocks
private CentralController controller;
#Mock
DgUserAuthorities dgUserAuthorities;
Annotations require a call to MockitoAnnotations.initMocks(this) or using a Mockito Extension: #ExtendWith(MockitoExtension.class)
I strongly discourage you to mix the 2 approaches.
Also, if you use annotations, do not initialize the fields yourself.
Related
Now I have some other library beans that implement initializingBeans and add some time-consuming methods, but I don't want to actually execute them, I need the Spring environment, but this bean I can mock it to reduce the overall test time, what should I do
This is the pseudo code of the bean of Mock:
public final class TimeoutBean implements InitializingBean, ApplicationContextAware, ApplicationListener {
#Override
public void afterPropertiesSet() throws Exception {
initProc();
}
/**
* init
*/
public void initProc() {
//... Something time-consuming and irrelevant to this test
}
}
And my mock unit test code:
#SpringBootTest(classes = Application.class)
#DelegateTo(SpringJUnit4ClassRunner.class)
public class MockTest {
#MockBean
private TimeoutBean timeoutBean;
#Resource
private MyRepository myRepository;
#SneakyThrows
#Test
public void test() {
doNothing().when(timeoutBean).initProc();
myRepository.getById(1L);
}
}
In this way, the Mock initProc method is invalid. I can probably understand because #MockBean calls after InitializingBean#afterPropertiesSet. When the afterPropertiesSet is executed, TimeoutBean is not an Mock object, but I don't know how to solve it.
Your class TimeoutBean is final and mockito cannot mock final classes. So first you will have to fix that. After that I think it should work. For mocked classes you don't have to tell mockito to doNothing() becease that is the default behaviour for mocks.
I don't understand what you mean with: the Mock initProc method is invalid?
i'm trying to make Unit Test testing a simple GET controller method apply MockMvc.perform method but when the controller receive a request the method Mockito.when seems to doesn't manage the method call of MenuService and the test throw an exception. The Exception says menuServiceMock is null
I'm working with Mockito MockMvc JUnit
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import edu.AG.LandingPageSanpietro.domain.Menu;
import edu.AG.LandingPageSanpietro.service.MenuService;
import java.util.Arrays;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
class MenuControllerTest {
private MockMvc mockMvc;
#Autowired
private MenuService menuServiceMock;
#Test
public void testHomeController1() throws Exception {
Menu first=new Menu("titolo1","descrizione1","filename1");
Menu second=new Menu("titolo2","descrizione2","filename2");
Mockito.when(menuServiceMock.getMenus()).thenReturn(Arrays.asList(first, second));
mockMvc.perform(get("/manageMenu"))
.andExpect(status().isOk())
.andExpect(view().name("manageMenu"))
.andExpect(forwardedUrl("/src/main/resources/tamplates/manageMenu.html"))
.andExpect(model().attribute("menus", hasSize(2)));
}
My Controller
#GetMapping("/manageMenu")
public String chiamataGestisciMenu(Model model) {
model.addAttribute("menus", menuService.getMenus());
return "manageMenu";
}
The error
java.lang.NullPointerException: Cannot invoke "edu.AG.LandingPageSanpietro.service.MenuService.getMenus()" because "this.menuServiceMock" is null
at edu.AG.LandingPageSanpietro.controller.MenuControllerTest.testHomeController1(MenuControllerTest.java:44)
I can't understand why when() method doesn't manage my menuServiceMock.getMenus() request for returning the specified list.
Use the annotation #Mock from mockito instead of #Autowired.
Seems like you have not initialized MockMvc. Try Autowiring it or initialize it in #Before method:
#RunWith(SpringJUnit4ClassRunner.class)
#WebMvcTest(controllers = ControllerToBeTested.class)
class MenuControllerTest {
#Autowired
private MockMvc mockMvc;
...
or you can even initialize it in #Before lik this:
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.standaloneSetup(new ControllerToBeTested()).build();
}
I'm trying to write a test case for a query dsl, I'm getting null pointer exception when I run the test case
Dsl Class
QMyClass myClass= QMyClass.myClass;
queryFactory = new JPAQueryFactory(em);
JPAQuery<?> from = queryFactory.from(myClass);
JPAQuery<?> where = from
.where(prepdicates);
orderBy(orderSpecifier).offset(sortOrder.getOffset())
.limit(sortOrder.getPageSize());
**Junit test case:**
import javax.inject.Provider;
import javax.persistence.EntityManager;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.data.jpa.repository.support.QueryDslRepositorySupport;
import com.querydsl.core.types.OrderSpecifier;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.JPQLTemplates;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
#RunWith(PowerMockRunner.class)
public class MyClass{
#Mock
QueryDslRepositorySupport queryDslRepositorySupport;
#Mock
EntityManager entityManager;
#Mock
JPAQueryFactory queryFactory;
#Mock
JPAQuery step1;
#InjectMocks
MyClass myClass;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Provider<EntityManager> provider = new Provider<EntityManager>() {
#Override
public EntityManager get() {
return entityManager;
}
};
queryFactory = new JPAQueryFactory(JPQLTemplates.DEFAULT, provider);
}
#SuppressWarnings({ "rawtypes", "unchecked" })
#Test
public void sampleTest() throws Exception {
QMyClass class= Mockito.mock(QMyClass.class);
Mockito.when(queryFactory.from(class)).thenReturn(step1);
Predicate step2 = Mockito.mock(Predicate.class);
Mockito.when(step1.where(step2)).thenReturn(step1);
OrderSpecifier step3 = Mockito.mock(OrderSpecifier.class);
Mockito.when(step1.orderBy(step3)).thenReturn(step1);
Mockito.when(step1.offset(Mockito.anyLong())).thenReturn(step1);
Mockito.when(step1.limit(Mockito.anyLong())).thenReturn(step1);
myClass.method("");
}
}
When I run this test case I'm getting null pointer exception at line number 2 in sampleTest() method. I googled but did't find any article for this, not sure why this NE, even after mocking the queryfacotry
Here is the trace :
java.lang.NullPointerException
at com.querydsl.core.DefaultQueryMetadata.addJoin(DefaultQueryMetadata.java:154)
at com.querydsl.core.support.QueryMixin.from(QueryMixin.java:163)
at com.querydsl.jpa.JPAQueryBase.from(JPAQueryBase.java:77)
at com.querydsl.jpa.impl.JPAQueryFactory.from(JPAQueryFactory.java:116)
at
As I mentioned in the comment, your problem is that you do not use a mock, but the real object instead.
Remove the queryFactory initialisation from your setup method.
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Provider<EntityManager> provider = new Provider<EntityManager>() {
#Override
public EntityManager get() {
return entityManager;
}
};
// remove this line
// queryFactory = new JPAQueryFactory(JPQLTemplates.DEFAULT, provider);
}
Also you need to change your implementation, you can not use
queryFactory = new JPAQueryFactory(em); inside your code, as it can not be mocked.
What you could do instead is having a method that returns the JPAQueryFactory,
either from another class - which you can mock -
or in the same method, then you would need to spy on your class instead.
As you didnt add the code for the class you want to test (MyClass - hopefully a different one from the identical named UnitTest?), another possibility would be that you try to use Field or Constructor Injection (as indicated by the use of your annotations), but then there should not be an object creation for the JPAQueryFactory in your code at all.
This also seems to be wrong:
You should inject mocks into your class under test, not in your UnitTest class.
#RunWith(PowerMockRunner.class)
public class MyClass{
...
#InjectMocks
MyClass myClass;
How to mock "System.getenv("...")" in JUnit.
Currently I am doing:
#RunWith(Parameterized.class)
#PowerMockRunnerDelegate(PowerMockRunner.class)
#PrepareForTest(System.class)
public class TestClass extends BaseTest {
public TestClass(String testCase) {
this.testCase = testCase;
}
#Before
#Override
public final void initTable() throws Throwable {
super.initTable();
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getenv("ENV_VAR1")).thenReturn("1234");
}
...
}
I am using both PowerMock and Parameterizedrunner.
I am getting below exception for line:
PowerMockito.when(System.getenv("ENV_VAR1")).thenReturn("1234");
Exception:
org.mockito.exceptions.base.MockitoException:
'afterPropertiesSet' is a *void method* and it *cannot* be stubbed with a *return value*!
Voids are usually stubbed with Throwables:
doThrow(exception).when(mock).someVoidMethod();
***
Use the #RunWith(PowerMockRunner.class) annotation at the class-level of the test case.
Use the #PrepareForTest({ClassThatCallsTheSystemClass.class}) annotation at the class-level of the test case.
Example with using EasyMock
public class SystemClassUser {
public String performEncode() throws UnsupportedEncodingException {
return URLEncoder.encode("string", "enc");
}
}
And test
#RunWith(PowerMockRunner.class)
#PrepareForTest( { SystemClassUser.class })
public class SystemClassUserTest {
#Test
public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
mockStatic(URLEncoder.class);
expect(URLEncoder.encode("string", "enc")).andReturn("something");
replayAll();
assertEquals("something", new SystemClassUser().performEncode());
verifyAll();
}
}
From:
https://github.com/powermock/powermock/wiki/MockSystem
So, you should add a class that uses the System.getenv, not the System class to #PrepareForTest.
This post explains why it should be done in such way.
Also, I'd like to recommend to use the System Rules library for your case. It has a good way to stub environment variables. PowerMock modifies a class byte code, so it makes test slowly. And even if it not modify a class it at least read class from disk.
Does anyone have idea about writing unit test case for ATG using Mockito? I came across following discussions while goggling -
Automated unit tests for ATG development and
Using PowerMock to obtain the ATG Nucleus in testing results in NPE
But need a help in setting up Nucleus and other dependencies (DAS, DPS, DSS etc.) and a sample test class for droplet using Mockito.
We are using ATG Dust where we have to set all the dependencies. I am wondering if we can replace ATG Dust completely with Mockito. Here is the example how we are writing the test cases -
A Base class for setting Nucleus -
package com.ebiz.market.support;
import java.io.File;
import java.util.Arrays;
import atg.nucleus.NucleusTestUtils;
import atg.test.AtgDustCase;
import atg.test.util.FileUtil;
public class BaseTestCase extends AtgDustCase {
public atg.nucleus.Nucleus mNucleus = null;
private final String ATGHOME="C://ATG/ATG9.4//home";
private final String ATGHOMEPROPERTY = "atg.dynamo.home";
protected void setUp() throws Exception {
super.setUp();
String dynamoHome = System.getProperty(ATGHOMEPROPERTY);
if(dynamoHome == null)
System.setProperty(ATGHOMEPROPERTY, ATGHOME);
File configpath = NucleusTestUtils.getConfigpath(this.getClass(), this.getClass().getName(), true);
FileUtil.copyDirectory("src/test/resources/config/test/", configpath.getAbsolutePath(), Arrays.asList(new String [] {".svn"}));
copyConfigurationFiles(new String[]{"config"}, configpath.getAbsolutePath(), ".svn");
}
public File getConfigPath() {
return NucleusTestUtils.getConfigpath(this.getClass(), this.getClass().getName(), true);
}
}
Writing the test case by extending the base class -
public class BizDropletTest extends BaseTestCase {
private BizDroplet bizDroplet;
#Before
public void setUp() throws Exception {
super.setUp();
mNucleus = NucleusTestUtils.startNucleusWithModules(new String[] { "DSS", "DPS", "DAFEAR" }, this.getClass(),
this.getClass().getName(), "com/ebiz/market/support/droplet/BizDroplet");
autoSuggestDroplet = (AutoSuggestDroplet) mNucleus.resolveName("com/ebiz/market/support/droplet/BizDroplet");
try {
bizDroplet.doStartService();
} catch (ServiceException e) {
fail(e.getMessage());
}
}
/**
Other methods
*/
}
So, how Mockito can handle these? Again, for me the target is to replace ATG Dust with Mockito completely because ATG Dust take lot of time in running tests due to huge dependencies.
Thanks.
Using Mockito you don't setup Nucleus or other dependencies (unless you need it). You simply mock the objects that you need to use.
Consider a simple class ProductUrlDroplet that retrieves a product from the repository and then outputs a url based on this. The service method would look something like this:
public void service(DynamoHttpServletRequest pRequest, DynamoHttpServletResponse pResponse) throws ServletException, IOException {
Object product = pRequest.getObjectParameter(PRODUCT_ID);
RepositoryItem productItem = (RepositoryItem) product;
String generatedUrl = generateProductUrl(pRequest, productItem.getRepositoryId());
pRequest.setParameter(PRODUCT_URL_ID, generatedUrl);
pRequest.serviceParameter(OPARAM_OUTPUT, pRequest, pResponse);
}
private String generateProductUrl(DynamoHttpServletRequest request, String productId) {
HttpServletRequest originatingRequest = (HttpServletRequest) request.resolveName("/OriginatingRequest");
String contextroot = originatingRequest.getContextPath();
return contextroot + "/browse/product.jsp?productId=" + productId;
}
A simple test class for this will then be:
public class ProductUrlDropletTest {
#InjectMocks private ProductUrlDroplet testObj;
#Mock private DynamoHttpServletRequest requestMock;
#Mock private DynamoHttpServletResponse responseMock;
#Mock private RepositoryItem productRepositoryItemMock;
#BeforeMethod(groups = { "unit" })
public void setup() throws Exception {
testObj = new ProductUrlDroplet();
MockitoAnnotations.initMocks(this);
Mockito.when(productRepositoryItemMock.getRepositoryId()).thenReturn("50302372");
}
#Test(groups = { "unit" })
public void testProductURL() throws Exception {
Mockito.when(requestMock.getObjectParameter(ProductUrlDroplet.PRODUCT_ID)).thenReturn(productRepositoryItemMock);
testObj.service(requestMock, responseMock);
ArgumentCaptor<String> argumentProductURL = ArgumentCaptor.forClass(String.class);
Mockito.verify(requestMock).setParameter(Matchers.eq(ProductUrlDroplet.PRODUCT_URL_ID), argumentProductURL.capture());
Assert.assertTrue(argumentProductURL.getValue().equals("/browse/product.jsp?productId=50302372"));
}
}
The key components are that you need to initialise the class you want to test (testObj). You then simply construct the response for each of the input parameters of the objects you are going to use (in this case productRepositoryItemMock represents the RepositoryItem and productRepositoryItemMock.getRepositoryId() returns a String that you can then test against later).
You will also notice that this test only validates the service method and not the individual methods. How you do it is up to you but generally I've been focused on testing my service and handleXXX methods in the formhandlers and droplets.
Testing the XXXManager, XXXUtil and XXXService classes will all have their own tests and should be 'mocked' into the droplets and formhandlers. For these I would write tests for each method though.
PowerMockito only really comes into the picture when you need to mock static methods and classes and the documentation does enough to explain that.