cannot resolve method "when" - mockito

I'm following the Vogella tutorial on Mockito and get stuck pretty much immediately. IntelliJ displays cannot resolve method 'when' for the class below.
...what did I miss?
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class MockitoTest {
#Test
public void test1() {
MyClass test = Mockito.mock(MyClass.class);
// define return value for method getUniqueId()
test.when(test.getUniqueId()).thenReturn(43);
// TODO use mock in test....
}
}

The method when() is not part of your class MyClass. It's part of the class Mockito:
Mockito.when(test.getUniqueId()).thenReturn(43);
or, with a static import:
import static org.mockito.Mockito.*;
...
when(test.getUniqueId()).thenReturn(43);

you are trying to get when from the mocked class. You need to do something like:
...
MyClass test = Mockito.mock(MyClass.class);
Mockito.when(test.getUniqueId()).thenReturn(43);
...

Related

Mockito.when method doesn't manage my service call

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();
}

Junit mockito unit test case gives null pointer exception

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.

Junit for QueryDsl

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;

Mock a specific constructor

mockito-1.10.19
powermock-mockito-1.7.1
powermock-1.7.4
junit 4.12
I have a class that has multiple constructors (java). Once constructor calls the other. I want to mock only 1 of the constructors (the one that is called from the other). I cannot change the code unfortunately - I am just testing it. Here is the class to be tested:
import java.io.File;
import java.sql.connection;
public class Foo {
public Foo (Connection connection){
this(connection, new File ());
}
public Foo (Connection connection, File file){
// do stuff
}
// other methods
}
Here is the test class I have written:
import java.io.File;
import java.sql.connection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.legacy.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(Foo.class)
#PowerMockIgnore("javax.management.*")
public class FooTest {
#Test
public void testFoo() throws Exception {
Connection mockConnection = Mockito.mock(Connection.class);
Foo fooObj = Mockito.mock(Foo.class);
PowerMockito.whenNew(Foo.class).withArguments(Matchers.notNull(), Matchers.notNull()).thenReturn(fooObj);
Foo newFooObj = new Foo (mockConnection);
assertNotNull ("newFooObj should not be null", newFooObj);
}
}
The problem is that Foo(Connection) is not being entered. Is there something I am missing?
I tried your code with the latest 1.7.x version of Powermock (1.7.4) and it works as you wanted it to. So you might just need to upgrade a few minor versions.

Mocking methods of local scope objects with Mockito

I need some help with this:
Example:
void method1{
MyObject obj1=new MyObject();
obj1.method1();
}
I want to mock obj1.method1() in my test but to be transparent so I don't want make and change of code.
Is there any way to do this in Mockito?
The answer from #edutesoy points to the documentation of PowerMockito and mentions constructor mocking as a hint but doesn't mention how to apply that to the current problem in the question.
Here is a solution based on that. Taking the code from the question:
public class MyClass {
void method1 {
MyObject obj1 = new MyObject();
obj1.method1();
}
}
The following test will create a mock of the MyObject instance class via preparing the class that instantiates it (in this example I am calling it MyClass) with PowerMock and letting PowerMockito to stub the constructor of MyObject class, then letting you stub the MyObject instance method1() call:
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class MyClassTest {
#Test
public void testMethod1() {
MyObject myObjectMock = mock(MyObject.class);
when(myObjectMock.method1()).thenReturn(<whatever you want to return>);
PowerMockito.whenNew(MyObject.class).withNoArguments().thenReturn(myObjectMock);
MyClass objectTested = new MyClass();
objectTested.method1();
... // your assertions or verification here
}
}
With that your internal method1() call will return what you want.
If you like the one-liners you can make the code shorter by creating the mock and the stub inline:
MyObject myObjectMock = when(mock(MyObject.class).method1()).thenReturn(<whatever you want>).getMock();
If you really want to avoid touching this code, you can use Powermockito (PowerMock for Mockito).
With this, amongst many other things, you can mock the construction of new objects in a very easy way.
No way. You'll need some dependency injection, i.e. instead of having the obj1 instantiated it should be provided by some factory.
MyObjectFactory factory;
public void setMyObjectFactory(MyObjectFactory factory)
{
this.factory = factory;
}
void method1()
{
MyObject obj1 = factory.get();
obj1.method();
}
Then your test would look like:
#Test
public void testMethod1() throws Exception
{
MyObjectFactory factory = Mockito.mock(MyObjectFactory.class);
MyObject obj1 = Mockito.mock(MyObject.class);
Mockito.when(factory.get()).thenReturn(obj1);
// mock the method()
Mockito.when(obj1.method()).thenReturn(Boolean.FALSE);
SomeObject someObject = new SomeObject();
someObject.setMyObjectFactory(factory);
someObject.method1();
// do some assertions
}
Both mocking of a new instance creation and static methods is possible without PowerMock in the latest mockito versions and junit5.
Take a look in the methods Mockito.mockConstruction() and Mockito.mockStatic().
In your case:
try (MockedConstruction<MyObject> myobjectMockedConstruction = Mockito.mockConstruction(MyObject.class,
(mock, context) -> {
given(mock.method1()).willReturn("some result"); //any additional mocking
})) {
underTest.method1();
assertThat(myobjectMockedConstruction.constructed()).hasSize(1);
MyObject mock = myobjectMockedConstruction.constructed().get(0);
verify(mock).method1();
}
You could avoid changing the code (although I recommend Boris' answer) and mock the constructor, like in this example for mocking the creation of a File object inside a method. Don't forget to put the class that will create the file in the #PrepareForTest.
package hello.easymock.constructor;
import java.io.File;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest({File.class})
public class ConstructorExampleTest {
#Test
public void testMockFile() throws Exception {
// first, create a mock for File
final File fileMock = EasyMock.createMock(File.class);
EasyMock.expect(fileMock.getAbsolutePath()).andReturn("/my/fake/file/path");
EasyMock.replay(fileMock);
// then return the mocked object if the constructor is invoked
Class<?>[] parameterTypes = new Class[] { String.class };
PowerMock.expectNew(File.class, parameterTypes , EasyMock.isA(String.class)).andReturn(fileMock);
PowerMock.replay(File.class);
// try constructing a real File and check if the mock kicked in
final String mockedFilePath = new File("/real/path/for/file").getAbsolutePath();
Assert.assertEquals("/my/fake/file/path", mockedFilePath);
}
}
If you don't prefer to use PowerMock, you may try the below way:
public class Example{
...
void method1(){
MyObject obj1 = getMyObject();
obj1.doSomething();
}
protected MyObject getMyObject(){
return new MyObject();
}
...
}
Write your test like this:
#Mock
MyObject mockMyObject;
#Test
void testMethod1(){
Example spyExample = spy(new Example());
when(spyExample.getMyObject()).thenReturn(mockMyObject);
//stub if required
doNothing().when(mockMyObject.doSomething());
verify(mockMyObject).doSomething();
}
You can do this by creating a factory method in MyObject:
class MyObject {
public static MyObject create() {
return new MyObject();
}
}
then mock that with PowerMock.
However, by mocking the methods of a local scope object, you are depending on that part of the implementation of the method staying the same. So you lose the ability to refactor that part of the method without breaking the test. In addition, if you are stubbing return values in the mock, then your unit test may pass, but the method may behave unexpectedly when using the real object.
In sum, you should probably not try to do this. Rather, letting the test drive your code (aka TDD), you would arrive at a solution like:
void method1(MyObject obj1) {
obj1.method1();
}
passing in the dependency, which you can easily mock for the unit test.

Resources