I don't want to use powermock anymore. Because junit5 started mocking static classes. So i am trying to get rid of powermock methods.
As you know, you can create an instance of a class with whenNew keyword.
Is there any alternative in Junit5 for whenNew?
Here is a part of my code:
whenNew(PDFDocument.class).withNoArguments().thenReturn(pdfDocument);
whenNew(PSConverter.class).withNoArguments().thenReturn(converter);
doNothing().when(pdfDocument).load(ArgumentMatchers.any(ByteArrayInputStream.class));
doAnswer(invocationOnMock -> {
ByteArrayOutputStream outputStream = invocationOnMock.getArgument(1);
outputStream.write(content);
return outputStream;
}).when(converter).convert(ArgumentMatchers.any(), ArgumentMatchers.any(ByteArrayOutputStream.class));
CodePudding user response:
Mocking object construction is available since Mockito 3.5.0 according to documentation.
First of all you need add the mockito-inline instead of the mockito-core
to your test dependencies.
mockito-inline
provides ability to mock static or final methods, constructors. Difference between mockito-core vs mockito-inline
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
Let's create a simple service for testing which instantiate objects.
public class A {
private final String test;
public A(String test) {
this.test = test;
}
public String check() {
return "checked " this.test;
}
}
public class B {
private String check = " B check ";
public String check() {
return check;
}
}
public class TestService {
public String purchaseProduct(String param) {
A a = new A(param);
B b = new B();
return a.check() b.check();
}
}
Example of constructor mock with comments:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedConstruction;
import org.mockito.Mockito;
import static org.mockito.Mockito.when;
public class ConstructorMockTest {
@Test
public void test_mocked_construction() {
try (
//create mock for object A
MockedConstruction<A> mockedA = Mockito.mockConstruction(A.class,
(mock, context) -> {
//set return value for object A mock methods
when(mock.check()).thenReturn(" Constructor Mock A ");
});
//create mock for object B
MockedConstruction<B> mockedB = Mockito.mockConstruction(B.class,
(mock, context) -> {
//set return value for object B mock methods
when(mock.check()).thenReturn(" Constructor Mock B ");
}))
{
// every A object creation is current try() scope returning a mock
A aObject = new A("test");
Assertions.assertEquals( aObject.check(), " Constructor Mock A ");
// every B object creation is current try() scope returning a mock
B bObject = new B();
Assertions.assertEquals( bObject.check(), " Constructor Mock B ");
//Example of testing service which creates A and B objects
TestService service = new TestService();
String serviceResult = service.purchaseProduct("test");
Assertions.assertEquals(serviceResult, " Constructor Mock A Constructor Mock B ");
}
}
}
For your classes example:
@Test
public void test() {
byte[] content = new byte[] {1,1};
try (
MockedConstruction<PDFDocument> mockedPDFDocument = Mockito.mockConstruction(PDFDocument.class,
(mock, context) -> {
doNothing().when(mock).load(ArgumentMatchers.any(ByteArrayInputStream.class));
});
MockedConstruction<PSConverter> mockedPSConverter = Mockito.mockConstruction(PSConverter.class,
(mock, context) -> {
doAnswer(invocationOnMock -> {
ByteArrayOutputStream outputStream = invocationOnMock.getArgument(1);
outputStream.write(content);
return outputStream;
}).when(mock).convert(ArgumentMatchers.any(), ArgumentMatchers.any(ByteArrayOutputStream.class));
}))
{
//call services which instantiates PDFDocument and PSConverter
PDFDocument pdfDocument = new PDFDocument();
PSConverter psConverter = new PSConverter();
Assertions.assertTrue(org.mockito.internal.util.MockUtil.isMock(pdfDocument));
Assertions.assertTrue(org.mockito.internal.util.MockUtil.isMock(psConverter));
}
}