Mockito - Impossible stubbing mocked object - java

I am newbie in Java world, but it is very hard understand why not can I stub method of a mocked object...
#RunWith(MockitoJUnitRunner.class)
public class ChildBLLIT extends BaseInteractorIT {
#InjectMocks
private ChildBLL ChildBLL = Mockito.mock(ChildBLL.class);
#Before
public void setUp() {
ChildBLL.engine = engineMock;
}
/**
* Test of getZipStatistics method, of class ChildBLL.
*/
#Test
public void testGetZipStatistics() {
final String testZipStatisticsText = "DummyZipStatistics";
//This method will throw the null pointer exception
when(ChildBLL.engine.getZIPStatistics()).thenReturn(testZipStatisticsText);
ChildBLL.getZipStatistics();
verify(ChildBLL.engine).getZIPStatistics();
}
}
When I try to stub the getZIPStatistics() method I get always a null pointer exception, of course I get, because in the getZIPStatistics() method there is an private object, which is not mocked... it seems to me the Mockito does not mocking the private fields... and unfortunately this is from another project:
public class BaseIT {
#Mock
protected static FromOtherProject engineMock;
#Before
public void initMocks() {
MockitoAnnotations.initMocks(this);
}
}
Here I mocked the engine variable, but then how can I mock/stub the getZIPStatistics() method? This is this method:
public class FromOtherProject {
//...
public final String getZIPStatistics() {
return ZIPStatistics.toString();
}
}
What can I do?

Let's assume a simple class...
public class Account {
public String getPassword() {
return "abc";
}
}
...and simple class that contains it...
public class AccountHolder {
private Account account;
public String getAccountPassword() {
return this.account.getPassword();
}
}
So now we have a simple base class for all Account based tests...
public class AccountBasedTest {
#Mock
protected Account account;
}
...and a class that actually tests the AccountHolder...
#RunWith(MockitoJUnitRunner.class)
public class AccountHolderTest extends AccountBasedTest {
#InjectMocks
private AccountHolder accountHolder;
#Test
public void getAccountPasswort_must_return_account_password() {
Mockito.when( this.account.getPassword() ).thenReturn ("xyz");
Assert.assertEquals("xyz", this.accountHolder.getAccountPassword());
}
}
And that's all. The #InjectMocks, etc. annotations will also look in the superclasses, so you get your mocked account and that account will be put into your AccountHolder. No need to call MockitoAnnotations.initMocks. It shouldn't hurt, but it's not needed because you are using the MockitoJUnitRunner already, which does exactly that.

Related

Why mock private method by use PowerMock.when actually call the real method

I try to learn PowerMockitoand write a demo
This the parent class A
public abstract class A {
protected String getRoot(Long id) {
if (id == 0) {
return "root";
}
return "not root";
}
}
And this is the childA
public class ChildA extends A {
private String info;
public String getRootInfo(Long id) {
String rootInfo = getRoot(id);
return rootInfo;
}
private void initRootInfo(String info) {
this.info = info;
}
}
And now i want to mock the method A::initRootInfo,so i write a test case like this
#RunWith(PowerMockRunner.class)
#PrepareForTest({A.class, ChildA.class})
public class ChildATest {
#Spy
#InjectMocks
private ChildA childA = PowerMockito.spy(new ChildA());
#Test
public void getRootInfoUT() throws Exception {
PowerMockito.doNothing().when(childA, "initRootInfo", Mockito.anyString());
String rootInfo = childA.getRootInfo(0L);
Assertions.assertEquals("root", rootInfo);
}
}
When i run the test case, the PowerMockito call the real method initRootInfo, so that i get a little bit confused why the A::initRootInfo will be called really, shouldn't it be mock and replaced by PowerMockito? is there have something wrong i use PowerMockito?
How to mock private method by PowerMockito correctly

Mocking a method inside a private method

I have the below flow
#InjectMocks private ClassToTest classToTest;
#Mock private ClassToInject classToInject;
#Before
public void setup() {
initMocks(this);
}
#Test
public void test() {
Classx mockClassObj = Mockito.mock(Classx.class);
when(classToInject.publicMethod1(mockClassObj)).thenReturn(1000);
classToTest.publicMethod();
}
I want to test public method of classToTest. Now this method makes call to a private method, which I am not mocking. Inside this private method another public method is called, which I want to mock publicMethod1. Instead of the private method making use of value 1000 it is behaving as if the publicMethod1 was not mocked and I get NPE inside the flow of the method somewhere. I tried using #Spy with classToTest and also I am using init.mocks/#RunWith but it fails.
In short it is something like
ClassToTest. publicMethod --> ClassToTest.privateMethod(not mocking) --> ClassToInject.publicMethod1(want to mock)
The class looks like below
class ClassToTest {
#Inject ClassToInject classToInject;
public publicMethod() {
privateMethod();
}
private privateMethod() {
int x = classToInject.publicMethod1();
// use the return value
// throw exception
}
You mock classToInject.publicMethod1(mockClassObj) not classToInject.publicMethod1().
But your code invoked classToInject.publicMethod1();
int x = classToInject.publicMethod1(); // you invoked no parameter method
Check method which you want to invoke.
If You want to invoke classToInject.publicMethod1(), reference this code
#RunWith(MockitoJUnitRunner.class)
public class MockedTest {
#InjectMocks
private ClassToTest classToTest;
#Mock
private ClassToInject classToInject;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() {
Mockito.when(classToInject.publicMethod1())
.thenReturn(1000);
classToTest.publicMethod();
}
}
class ClassToTest{
ClassToInject classToInject;
public void publicMethod() {
privateMethod();
}
private int privateMethod() {
int x = classToInject.publicMethod1();
throw new NullPointerException(String.valueOf(x));
}
}
class ClassToInject{
public int publicMethod1() {
return 0;
}
}
The result is 1000 success
java.lang.NullPointerException: 1000

Mockito's thenCallRealMethod , not calling public method

I am trying to call the real method in my testing class.
there are two methods one is public void m2() and another private void m3() in mapper class.
but here only private method gets execute and public method doesn't gets call.
Sample code is like.
public class Service {
#Autowired
Mapper mapper;
public void m1(String s){
System.out.println(s);
mapper.m1(s);
}
}
public class Mapper {
public String m1(String s){
System.out.println("inside m1 method" +s);
m2();
m3();
return s;
}
public void m2(){
System.out.println("inside m2 public method");
}
private void m3(){
System.out.println("insid m3 private method");
}
}
#RunWith(MockitoJUnitRunner.class)
public class Testing {
#Mock
Mapper mapper;
#InjectMocks
Service service;
#Test
public void test(){
when(mapper.m1(Mockito.any(String.class))).thenCallRealMethod();
service.m1("Check");
}
/**
* #param m1
*/
}
Public method is not called because you don't instruct mock to do so.
Private method is called because mockito doesn't affect private methods (You have to summon dark magic of PowerMock to do so).

Mockito mocked method is returning NULL

I am using Mockito and have tried to mock the below test class.
Here the main class method createNewId() is getting the object by hitting dao class 'memberDao.findNext()'.
I am trying to mock 'memberDao.findNext()' and return the object as shown in below code but it is returning as NULL.
ALSO how to write Test for void method which is "memberDao.delete(newId.getId());"
Need to implement this after this line "when(memberDao.findNext()).thenReturn(id);"
Please let me know what am i doing wrong.
#RunWith(MockitoJUnitRunner.class)
public class MemberTest
{
#InjectMocks
private Member member;
#Mock
private MemberDao memberDao;
#Test
public void createId() throws Exception
{
MembersIdDto id = new MembersIdDto();
id.setId("967405286");
when(memberDao.findNext()).thenReturn(id);
verify(member).createNewId().contains("967405286");
}
public class Member {
#Resource
MemberDao memberDao;
public String createNewId()
{
MembersIdDto newId = memberDao.findNext();
Assert.notNull(newId, "newId is empty");
String id = newId.getId();
memberDao.delete(newId.getId());
return id;
}
}
memberDao.findNext() is the line i am trying to mock.
Error is :
java.lang.IllegalArgumentException: newId is empty
at org.springframework.util.Assert.notNull(Assert.java:134)
at Member.createNewId() (Member.java:20)
// Line 20 is "Assert.notNull(newId, "newId is empty");"
A working example of your requirement could be:
#RunWith(MockitoJUnitRunner.class)
public class MemberTest {
#InjectMocks
private Member member;
#Mock
private MemberDao memberDao;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void createId() throws Exception {
MembersIdDto dto = new MembersIdDto();
dto.setId("967405286");
when(memberDao.findNext()).thenReturn(dto);
assertThat(member.createNewId()).isEqualTo("967405286");
}
}
…with the classes-under-test…
public class Member {
#Resource
MemberDao memberDao;
public String createNewId() {
return memberDao.findNext().getId();
}
}
…and…
public class MemberDao {
public MembersIdDto findNext() {
return null; // or whatever
}
}
…and…
import lombok.Data;
import lombok.NoArgsConstructor;
#Data
#NoArgsConstructor
public class MembersIdDto {
private String id;
}
By the way, I use the AssertJ assertion framework and with member.createNewId() you have now a real call on production code.
You're creating two instances of MemberDao. First MockitoJUnitRunner creates an instance, assigns it to the field memberDao and injects that instance into the Member object. Afterwards in the method setUp you create a new instance of the DAO and assign it to the field memberDao. Therefore the field memberDao is no longer the same as the Member's DAO. While you define behaviour on the field, the Member object is still using the first DAO that has no behaviour defined. Therefore memberDao.findNext() in Member#createNewId returns null.
Fortunately the solution is very simple: Delete the setUp method in your test.

Mockito: How to test my Service with mocking?

I'm new to mock testing.
I want to test my Service method CorrectionService.correctPerson(Long personId).
The implementation is not yet written but this it what it will do:
CorrectionService will call a method of AddressDAO that will remove some of the Adress that a Person has. One Person has Many Addresses
I'm not sure what the basic structure must be of my CorrectionServiceTest.testCorrectPerson.
Also please do/not confirm that in this test i do not need to test if the adresses are actually deleted (should be done in a AddressDaoTest), Only that the DAO method was being called.
Thank you
Cleaner version:
#RunWith(MockitoJUnitRunner.class)
public class CorrectionServiceTest {
private static final Long VALID_ID = 123L;
#Mock
AddressDao addressDao;
#InjectMocks
private CorrectionService correctionService;
#Test
public void shouldCallDeleteAddress() {
//when
correctionService.correct(VALID_ID);
//then
verify(addressDao).deleteAddress(VALID_ID);
}
}
A simplified version of the CorrectionService class (visibility modifiers removed for simplicity).
class CorrectionService {
AddressDao addressDao;
CorrectionService(AddressDao addressDao) {
this.addressDao;
}
void correctPerson(Long personId) {
//Do some stuff with the addressDao here...
}
}
In your test:
import static org.mockito.Mockito.*;
public class CorrectionServiceTest {
#Before
public void setUp() {
addressDao = mock(AddressDao.class);
correctionService = new CorrectionService(addressDao);
}
#Test
public void shouldCallDeleteAddress() {
correctionService.correct(VALID_ID);
verify(addressDao).deleteAddress(VALID_ID);
}
}

Categories