Junit 5 使用 mockConstruction().withSetting().useConstructor() 而不是 PowerMock.whenNew().withArguments()
Junit 5 use mockConstruction().withSetting().useConstructor() instead of PowerMock.whenNew().withArguments()
现在我想使用 Junit 5 + Mockito 4.x 版本 + Mockito-inline 4.x 版本而不是 Junit 4 + PowerMock 2.0.9
因为 Junit 5 不支持 PowerMock 也 Mockito-inline 可以模拟静态,看起来它不再需要 PowerMock。
但是当我使用 Mockito 模拟静态时,我想使用与 Powermock.whenNew(xxx.class).withArgument(1,2,3,4).thanReturn(someThing) 相同的效果。
这是我的代码的一部分,它可以工作。
@Test
void get_report_page() {
ReportPageRequest reportPageRequest = prepare_request();
prepare_reportPage(context, 9999L, pageable);
when(reportConverter.toReportSpecification(user, reportPageRequest)).thenReturn(reportSpecification);
when(PageRequest.of(1, 100)).thenReturn(pageRequest);
when(reportRepository.findAll(reportSpecification, pageRequest)).thenReturn(reportPage);
when(reportConverter.toReportPageResponse(context)).thenReturn(reportPageResponses);
pageMockedConstruction = Mockito.mockConstruction(PageImpl.class,
withSettings().useConstructor(reportPageResponses, pageable, 9999L), (mock, context) -> {
when(mock.getTotalElements()).thenReturn(123456L);
when(mock.getTotalPages()).thenReturn(1);
when(mock.getContent()).thenReturn(reportPageResponses);
});
Page<ReportPageResponse> actual = sut.getReportPage(user, reportPageRequest);
assertThat(actual.getTotalElements()).isEqualTo(123456L);
assertThat(actual.getTotalPages()).isEqualTo(1);
assertThat(actual.getContent()).isEqualTo(reportPageResponses);
}
}
我的问题是我只能验证模拟静态对象的行为,但无法验证结果,这是我的尝试
pageMockedConstruction = Mockito.mockConstruction(PageImpl.class,
withSettings().useConstructor(reportPageResponses, pageable, 9999L), (mock, context) -> {
when(mock.getTotalElements()).thenReturn(123456L);
when(mock.getTotalPages()).thenReturn(1);
when(mock.getContent()).thenReturn(reportPageResponses);
});
// I thought here will be the same mock object
// when expected and actual will throught the Mockito.mockConstruction, but actually generate the different object
PageImpl<ReportPageResponse> expected = new PageImpl<>(this.reportPageResponses, pageable, 9999L);
Page<ReportPageResponse> actual = sut.getReportPage(user, reportPageRequest);
// Here will be wrong, because actual and expected has different hashCode
Assertions.assertThat(actual).isEqualTo(expected);
我研究了很多文章,但找不到答案。
有人遇到过同样的问题吗?
Powermock.whenNew
和Mockito.mockConstruction
的主要区别是Mokito
在调用构造函数时每次实例化新对象时都会创建一个新的mock。但是 Powermock.whenNew
可以配置为 return 一个 mock 总是用于构建多个对象。
根据documentation:
Represents a mock of any object construction of the represented type.
Within the scope of the mocked construction, the invocation of any
interceptor will generate a mock which will be prepared as specified
when generating this scope. The mock can also be received via this
instance.
您可以使用 MockedConstruction<T>.constructed()
在上下文中获取所有生成的模拟。它们可以用于验证。
检查行为的测试示例:
public class A {
private final String test;
public A(String test) {
this.test = test;
}
public String check() {
return "checked " + this.test;
}
}
public class TestService {
public String purchaseProduct(String param) {
A a = new A(param);
return a.check();
}
}
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedConstruction;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
public class ConstructorMockTest {
private MockedConstruction<A> mockAController;
@BeforeEach
public void beginTest() {
//create mock controller for all constructors of the given class
mockAController = Mockito.mockConstruction(A.class,
(mock, context) -> {
//implement initializer for mock. Set return value for object A mock methods
//this initializer will be called each time during mock creation
when(mock.check()).thenReturn(" Constructor Mock A ");
});
}
@Test
public void test() {
//each instantiation of class A will return new mock, which initialized by initializer from beginTest method
//new mock will be stored to mockAController.constructed() collection of mocks
A aObject = new A("test");
//ensure that method check() returns mocked value
Assertions.assertEquals(aObject.check(), " Constructor Mock A ");
//get just created mock for class A from controller. It will be first element of mockAController.constructed() collection
A aMock = mockAController.constructed().get(0);
//ensure that we get correct mock from mock controller, that it is equal from new created object
Assertions.assertEquals(aMock, aObject);
//verify that check method was executed on Mock
verify(aMock, times(1)).check();
//create new A object, new mock created and stored to mockAController.constructed()
A aObject2 = new A("test");
//ensure that method check() returns mocked value
Assertions.assertEquals(aObject2.check(), " Constructor Mock A ");
//get just created mock for class A from controller, it will be second object from constructed collection
A aMock2 = mockAController.constructed().get(1);
//ensure that we get correct mock from mock controller, that it is equal from just created A object
Assertions.assertEquals(aObject2, aMock2);
//verify that check method was executed on Mock
verify(aMock2, times(1)).check();
//Example of testing service which creates A object
TestService service = new TestService();
String serviceResult = service.purchaseProduct("test");
//ensure that service returned value from A mock
Assertions.assertEquals(serviceResult, " Constructor Mock A ");
//get just created mock for class A from controller, it will be third object from constructed collection
A aMock3 = mockAController.constructed().get(2);
//verify that check method was executed on Mock
verify(aMock3, times(1)).check();
}
@AfterEach
public void endTest() {
mockAController.close();
}
}
现在我想使用 Junit 5 + Mockito 4.x 版本 + Mockito-inline 4.x 版本而不是 Junit 4 + PowerMock 2.0.9
因为 Junit 5 不支持 PowerMock 也 Mockito-inline 可以模拟静态,看起来它不再需要 PowerMock。
但是当我使用 Mockito 模拟静态时,我想使用与 Powermock.whenNew(xxx.class).withArgument(1,2,3,4).thanReturn(someThing) 相同的效果。
这是我的代码的一部分,它可以工作。
@Test
void get_report_page() {
ReportPageRequest reportPageRequest = prepare_request();
prepare_reportPage(context, 9999L, pageable);
when(reportConverter.toReportSpecification(user, reportPageRequest)).thenReturn(reportSpecification);
when(PageRequest.of(1, 100)).thenReturn(pageRequest);
when(reportRepository.findAll(reportSpecification, pageRequest)).thenReturn(reportPage);
when(reportConverter.toReportPageResponse(context)).thenReturn(reportPageResponses);
pageMockedConstruction = Mockito.mockConstruction(PageImpl.class,
withSettings().useConstructor(reportPageResponses, pageable, 9999L), (mock, context) -> {
when(mock.getTotalElements()).thenReturn(123456L);
when(mock.getTotalPages()).thenReturn(1);
when(mock.getContent()).thenReturn(reportPageResponses);
});
Page<ReportPageResponse> actual = sut.getReportPage(user, reportPageRequest);
assertThat(actual.getTotalElements()).isEqualTo(123456L);
assertThat(actual.getTotalPages()).isEqualTo(1);
assertThat(actual.getContent()).isEqualTo(reportPageResponses);
}
}
我的问题是我只能验证模拟静态对象的行为,但无法验证结果,这是我的尝试
pageMockedConstruction = Mockito.mockConstruction(PageImpl.class,
withSettings().useConstructor(reportPageResponses, pageable, 9999L), (mock, context) -> {
when(mock.getTotalElements()).thenReturn(123456L);
when(mock.getTotalPages()).thenReturn(1);
when(mock.getContent()).thenReturn(reportPageResponses);
});
// I thought here will be the same mock object
// when expected and actual will throught the Mockito.mockConstruction, but actually generate the different object
PageImpl<ReportPageResponse> expected = new PageImpl<>(this.reportPageResponses, pageable, 9999L);
Page<ReportPageResponse> actual = sut.getReportPage(user, reportPageRequest);
// Here will be wrong, because actual and expected has different hashCode
Assertions.assertThat(actual).isEqualTo(expected);
我研究了很多文章,但找不到答案。
有人遇到过同样的问题吗?
Powermock.whenNew
和Mockito.mockConstruction
的主要区别是Mokito
在调用构造函数时每次实例化新对象时都会创建一个新的mock。但是 Powermock.whenNew
可以配置为 return 一个 mock 总是用于构建多个对象。
根据documentation:
Represents a mock of any object construction of the represented type. Within the scope of the mocked construction, the invocation of any interceptor will generate a mock which will be prepared as specified when generating this scope. The mock can also be received via this instance.
您可以使用 MockedConstruction<T>.constructed()
在上下文中获取所有生成的模拟。它们可以用于验证。
检查行为的测试示例:
public class A {
private final String test;
public A(String test) {
this.test = test;
}
public String check() {
return "checked " + this.test;
}
}
public class TestService {
public String purchaseProduct(String param) {
A a = new A(param);
return a.check();
}
}
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedConstruction;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
public class ConstructorMockTest {
private MockedConstruction<A> mockAController;
@BeforeEach
public void beginTest() {
//create mock controller for all constructors of the given class
mockAController = Mockito.mockConstruction(A.class,
(mock, context) -> {
//implement initializer for mock. Set return value for object A mock methods
//this initializer will be called each time during mock creation
when(mock.check()).thenReturn(" Constructor Mock A ");
});
}
@Test
public void test() {
//each instantiation of class A will return new mock, which initialized by initializer from beginTest method
//new mock will be stored to mockAController.constructed() collection of mocks
A aObject = new A("test");
//ensure that method check() returns mocked value
Assertions.assertEquals(aObject.check(), " Constructor Mock A ");
//get just created mock for class A from controller. It will be first element of mockAController.constructed() collection
A aMock = mockAController.constructed().get(0);
//ensure that we get correct mock from mock controller, that it is equal from new created object
Assertions.assertEquals(aMock, aObject);
//verify that check method was executed on Mock
verify(aMock, times(1)).check();
//create new A object, new mock created and stored to mockAController.constructed()
A aObject2 = new A("test");
//ensure that method check() returns mocked value
Assertions.assertEquals(aObject2.check(), " Constructor Mock A ");
//get just created mock for class A from controller, it will be second object from constructed collection
A aMock2 = mockAController.constructed().get(1);
//ensure that we get correct mock from mock controller, that it is equal from just created A object
Assertions.assertEquals(aObject2, aMock2);
//verify that check method was executed on Mock
verify(aMock2, times(1)).check();
//Example of testing service which creates A object
TestService service = new TestService();
String serviceResult = service.purchaseProduct("test");
//ensure that service returned value from A mock
Assertions.assertEquals(serviceResult, " Constructor Mock A ");
//get just created mock for class A from controller, it will be third object from constructed collection
A aMock3 = mockAController.constructed().get(2);
//verify that check method was executed on Mock
verify(aMock3, times(1)).check();
}
@AfterEach
public void endTest() {
mockAController.close();
}
}