Mockito allows us to partially mock an object. This means that we can create a mock object and still be able to call a real method on it.
To call a real method on a mocked object we use Mockito’s thenCallRealMethod().
Also, I have recorded many step-by-step video lessons that teach how to test Java applications. If you are interested to learn more, have a look at my video course “Testing Java with Junit and Mockito“.
The Object to Be Mocked
Below is an example of a Plain Old Java Object which is being used to persist user details into a database. A bit later, when working on a test case, we will mock this object and stub two of its methods which are the getFirstName() and the getLastName() and the getFullName() will be called as a real method rather than stubbed.
package com.appsdeveloperblog.ws.io.entity; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; /** * * @author skargopolov */ @Entity(name = "Profile") public class UserProfileEntity implements Serializable { private static final long serialVersionUID = 7290798953394355234L; @Id @GeneratedValue private long id; private String firstName; private String lastName; private String fullName; /** * @return the firstName */ public String getFirstName() { return firstName; } /** * @param firstName the firstName to set */ public void setFirstName(String firstName) { this.firstName = firstName; } /** * @return the lastName */ public String getLastName() { return lastName; } /** * @param lastName the lastName to set */ public void setLastName(String lastName) { this.lastName = lastName; } /** * @return the id */ public long getId() { return id; } /** * @param id the id to set */ public void setId(long id) { this.id = id; } /** * @return the fullName */ public String getFullName() { if (fullName == null) { fullName = getFirstName() + " " + getLastName(); } return fullName; } /** * @param fullName the fullName to set */ public void setFullName(String fullName) { this.fullName = fullName; } }
Use Mockito to Mock an Object
To Mock UserProfileEntity object, we will annotate it with @Mock annotation and will call the MockitoAnnotations.initMocks(this); in the setUp() method like so:
@Mock UserProfileEntity userProfileEntity; @Before public void setUp() { MockitoAnnotations.initMocks(this); }
Stubbing Mock Object with Mockito
Now that you have learned how to mock UserProfileEntity, let’s continue and learn how to stub it with a predefined value.
// Stubbinb userProfileEntity methods when( userProfileEntity.getFirstName() ).thenReturn( "Sergey" ); when( userProfileEntity.getLastName()).thenReturn( "Kargopolov" ); when( userProfileEntity.getId() ).thenReturn( new Long(1) );
Call a Real Method
To call a real method of a mock object in Mockito we use the thenCallRealMethod() method.
// Call a real method of a Mocked object when( userProfileEntity.getFullName() ).thenCallRealMethod();
Test Class Complete Example
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.appsdeveloperblog.ws.service.impl; import com.appsdeveloperblog.ws.TestConfiguration; import com.appsdeveloperblog.ws.io.dao.Database; import com.appsdeveloperblog.ws.io.entity.UserProfileEntity; import com.appsdeveloperblog.ws.service.UsersService; import com.appsdeveloperblog.ws.shared.dto.UserProfileDto; import org.junit.*; import org.junit.runner.RunWith; import static org.mockito.ArgumentMatchers.any; import org.mockito.InjectMocks; import org.mockito.Mock; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; import org.mockito.MockitoAnnotations; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration( classes = TestConfiguration.class ) public class UsersServiceImplTest { @Mock Database database; @Mock UserProfileEntity userProfileEntity; @Autowired @InjectMocks @Qualifier("usersService") UsersService usersService; @Before public void setUp() { MockitoAnnotations.initMocks(this); } @Test public void testSaveUserWithFullName() { //Stubbing Database open and close methods doNothing().when(database).openConnection(); doNothing().when(database).closeConnection(); // Stubbing userProfileEntity methods when( userProfileEntity.getFirstName() ).thenReturn( "Sergey" ); when( userProfileEntity.getLastName()).thenReturn( "Kargopolov" ); when( userProfileEntity.getId() ).thenReturn( new Long(1) ); when( userProfileEntity.getFullName() ).thenCallRealMethod(); // Stubbing database saveUserProfile method when( database.saveUserProfile( any(UserProfileEntity.class) ) ).thenReturn( userProfileEntity ); // Create sample UserProfileDto UserProfileDto userProfileDto = new UserProfileDto(); userProfileDto.setFirstName( "Sergey" ); userProfileDto.setLastName( "Kargopolov" ); userProfileDto.setFullName( "Sergey Kargopolov" ); // Call saveUser method UserProfileDto result = usersService.saveUser( userProfileDto ); // Assert expected results Assert.assertNotNull( result ); Assert.assertEquals( userProfileDto.getFirstName() , result.getFirstName() ); Assert.assertEquals( userProfileDto.getLastName() , result.getLastName() ); Assert.assertNotNull( result.getFullName() ); Assert.assertEquals( userProfileEntity.getFullName() , result.getFullName() ); } }
I hope this little code example was helpful to you. If you are interested in learning more, have a look at other JUnit and Mockito tutorials on this site.
Happy learning!
I my case it does not work because the real method call also a injected (mocked) class which is null during test execution.
Is there something more I can do?
I mocked the already the internal injected class in my test.