How to Pass Interface or Abstract Class as Matcher?
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)); }
How to doNothing when internal method which returns void is gets called?
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)); }
How to doNothing when method which returns value is called?
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()); }
How to mock methods of private and public instance class variables?
- 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)); } }