Person.java
public interface Person {
}
StudentUtils.java
public String methodWithInterfaceArg(Person person)
{
//This method takes Interface Implementation as Parameter
Somemethod(person);
return "Test Success";
}
public void Somemethod(Person p){
System.out.println("Hello There");
}
StudentUtilsTest.java
@Test
@DisplayName("Test for method which takes interface as argument")
void methodWithInterfaceArg()
{
Person objPerson = Mockito.mock(Person.class);
// Using spy we are creating a new mock and call the method to be tested
StudentUtils studentUtils= Mockito.spy(StudentUtils.class);
doNothing().when(studentUtils).Somemethod(objPerson);
// While testing we should call the method to be tested using new spyObject rather than systemUnderTest
// This is because only in the Spy object studentUtils we have created a mock definition for Somemethod
// Hence when methodWithInterfaceArg is called using systemUnderTest the mock definition created using spy would be lost
assertEquals("Test Success", studentUtils.methodWithInterfaceArg(objPerson));
}
StudentUtils.java
public String methodWithInterfaceArg(Person person)
{
//This method has void return type
Somemethod(person);
return "Test Success";
}
public void Somemethod(Person p){
System.out.println("Hello There");
}
StudentUtilsTest.java
@Test
@DisplayName("Test for internal method which is of void return type")
void methodWithInterfaceArg() {
Person objPerson = Mockito.mock(Person.class);
// Using spy we are creating a new mock and call the method to be tested
StudentUtils studentUtils= Mockito.spy(StudentUtils.class);
//With Object Created using spy we can mock the actual method to do nothing
doNothing().when(studentUtils).Somemethod(objPerson);
assertEquals("Test Success", studentUtils.methodWithInterfaceArg(objPerson));
}
StudentUtils.java
public class StudentUtils {
private List arrStudents = new ArrayList();
private String Name = "Mugil";
public String dummymethod(Student objStudent)
{
System.out.println("Dummy Method Called");
return "Dummy Method";
}
public String methodCallingAnotherMethodReturningVal()
{
String something = dummymethod(new Student("102" ,"abc"));
return "Dummy Method returned "+ something;
}
}
StudentUtilsTest.java
@Test
@DisplayName("Test for Method calling another method which returns value")
void methodCallingAnotherMethodReturningVal() {
StudentUtils studentUtils= Mockito.spy(StudentUtils.class);
Mockito.when(studentUtils.dummymethod(any())).thenReturn("Test Student");
Assert.assertEquals("Dummy Method returned Test Student", studentUtils.methodCallingAnotherMethodReturningVal());
}
- The below scenario we are going to mock instance of method which belongs to other class initialized over by public and private class variables
- We Create a new mock and initialize using reflectionUtils for the objDBConnectionFactory which is private whereas we use a spy to directly change the method definition of objDBConnectionFactory2
DBConnectionFactory.java
package com.mugil.org;
public class DBConnectionFactory {
public DBConnectionFactory() {
}
public <T> T readDetails(byte[] src, Class<People> valueType){
return (T)new Student();
}
public <T> T readDetails2(String src){
return (T)new Student();
}
}
MockPrivateFileds.java
package com.mugil.org;
import org.springframework.web.client.HttpStatusCodeException;
public class MockPrivateFileds {
private DBConnectionFactory objDBConnectionFactory = new DBConnectionFactory();
public DBConnectionFactory objDBConnectionFactory2 = new DBConnectionFactory();
private Student getDetails(HttpStatusCodeException httpStatusCodeException) {
return objDBConnectionFactory.readDetails(httpStatusCodeException.getResponseBodyAsByteArray(), People.class);
}
public Student getDetails2(HttpStatusCodeException httpStatusCodeException) {
return objDBConnectionFactory2.readDetails2("String");
}
}
MockPrivateFiledsTest.java
package com.mugil.org;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.HttpStatusCodeException;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.mockito.ArgumentMatchers.*;
@ExtendWith({MockitoExtension.class})
class MockPrivateFiledsTest {
@InjectMocks
MockPrivateFileds systemUnderTest;
@Test
void getDetailsTest() {
HttpStatusCodeException httpStatusCodeException = Mockito.mock(HttpStatusCodeException.class);
/*The Below two lines of code are needed because the objDBConnectionFactory created doesnot contain any definition of methods
* So the definition could be set by creating new mock object as below. If there is Setter we can use setter to set the newly created mock object
* Since there is no setter and its private we are going to use reflectionUtils */
DBConnectionFactory dbConnectionFactory = Mockito.mock(DBConnectionFactory.class);
ReflectionTestUtils.setField(systemUnderTest, "objDBConnectionFactory", dbConnectionFactory);
Mockito.when(dbConnectionFactory.readDetails(nullable(byte[].class), eq(People.class))).thenReturn(new Student());
assertThat(ReflectionTestUtils.invokeMethod(systemUnderTest, "getDetails", httpStatusCodeException), instanceOf(Student.class));
}
@Test
void getDetailsTest2() {
HttpStatusCodeException httpStatusCodeException = Mockito.mock(HttpStatusCodeException.class);
systemUnderTest = Mockito.spy(MockPrivateFileds.class);
DBConnectionFactory dbConnectionFactory2 = Mockito.spy(DBConnectionFactory.class);
ReflectionTestUtils.setField(systemUnderTest, "objDBConnectionFactory2", dbConnectionFactory2);
/*Below is a mocking of a public method through its instance by using spy. The below case is similar to above
* scenario with the only difference we can use spy to gain access to readDetails2 */
Mockito.when(systemUnderTest.objDBConnectionFactory2.readDetails2(anyString())).thenReturn(new Student());
assertThat(systemUnderTest.getDetails2(httpStatusCodeException), instanceOf(Student.class));
}
}