我正在开发Spring Boot + Data JPA + Mockito
示例。我已经为Pagination
存储库方法开发了测试用例,但它给了我以下错误。
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced or misused argument matcher detected here:
-> at com.xxxx.EmployeeServiceTest.test_findAllEmployeesPaginated(EmployeeServiceTest.java:152)
-> at com.xxxx.EmployeeServiceTest.test_findAllEmployeesPaginated(EmployeeServiceTest.java:152)
-> at com.xxxx.EmployeeServiceTest.test_findAllEmployeesPaginated(EmployeeServiceTest.java:152)
-> at com.xxxx.EmployeeServiceTest.test_findAllEmployeesPaginated(EmployeeServiceTest.java:152)
You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
when(mock.get(anyInt())).thenReturn(null);
doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
verify(mock).someMethod(contains("foo"))
This message may appear after an NullPointerException if the last matcher is returning an object
like any() but the stubbed method signature expect a primitive argument, in this case,
use primitive alternatives.
when(mock.get(any())); // bad use, will raise NPE
when(mock.get(anyInt())); // correct usage use
Also, this error might show up because you use argument matchers with methods that cannot be mocked.
Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().
Mocking methods declared on non-public parent classes is not supported.
at com.xxxx.EmployeeServiceTest.test_findAllEmployeesPaginated(EmployeeServiceTest.java:152)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
控制器
@GetMapping()
public ResponseEntity<Page<Division>> getAllDivisionsPaginated(
@RequestParam(required = false, value="page") Integer page, @RequestParam(required = false, value = "size") Integer size,
@RequestParam(required = false) String sort,
@RequestParam(required = false) String direction,
Pageable pageable){
Page<Division> divisions = divisionService.findAllDivisions(pageable, page, size, sort, direction);
return new ResponseEntity<>(divisions, HttpStatus.OK);
}
方法:
public Page<Division> findAllEmployees(Pageable pageableReq, Integer page, Integer size, String sortBy, String direction) {
Pageable pageable = Utils.sort(pageableReq, page, size, sortBy, direction);
return employeeRepository.findByStatus(StatusEnum.A, pageable);
}
另一种方法:
public static Pageable sort(Pageable pageableReq, Integer page, Integer size, String sortBy, String direction) {
Pageable pageable = null;
if (page != null && size != null) {
if (direction.equalsIgnoreCase("ASC"))
pageable = PageRequest.of(page, size, Sort.by(sortBy).ascending());
else if (direction.equalsIgnoreCase("DESC"))
pageable = PageRequest.of(page, size, Sort.by(sortBy).descending());
} else {
pageable = pageableReq;
}
return pageable;
}
测试类:
@RunWith(PowerMockRunner.class)
@PrepareForTest({StatusEnum.class})
public class EmployeeServiceTest {
@Mock
private Employee employeeMock;
@InjectMocks
private EmployeeServiceImpl employeeServiceImpl;
@Mock
private EmployeeRepository employeeRepositoryMock;
@Mock
private EmployeeDto employeeDtoMock;
@Mock
private StatusEnum statusEnum;
@Mock
private Exception ex;
@Mock
private Pageable pageableMock;
@Mock
private Utils utils;
@Mock
private Page<Employee> employeePage;
@Before
public void setup() {
mockStatic(StatusEnum.class);
}
@Test
public void test_findAllEmployeesPaginated() {
Pageable pageable = PageRequest.of(0, 8);
when(Utils.sort(pageable, anyInt(), anyInt(), anyString(), anyString())).thenReturn(pageableMock);
when(employeeRepositoryMock.findByStatus(StatusEnum.A, pageableMock)).thenReturn(employeePage);
}
}
-
纯 Mockito 不能模拟静态方法。(您需要使用对象引用
utils
而不是类引用,但您的代码显示该方法是静态的(
如果你想在这里使用Powermock,你可能会缺少一个mockStatic(Utils.class(,但我不确定这是否与@Mock注释一起工作。 -
此外,您还必须更改排序方法的调用。您必须仅使用匹配器或仅使用实值。你不能混合它们。
-
关于跑步者
@RunWith(PowerMockRunner.class)
.如果你只写一个纯粹的JUnit 4测试和Mocktio,你应该考虑使用Mockito Runner。
否则,您需要在设置方法中使用MockitoAnnotations.initMocks(this);
初始化 Mockito。
(您没有使用 PowerMock 标记您的问题,但我认为这可能是不正确的。
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
mockStatic(StatusEnum.class);
}
@Test
public void test_findAllEmployeesPaginated() {
Pageable pageable = PageRequest.of(0, 8);
mockStatic(Utils.class);
when(Utils.sort(any(Pageable.class), anyInt(), anyInt(), anyString(), anyString())).thenReturn(pageableMock);
when(employeeRepositoryMock.findByStatus(StatusEnum.A, pageableMock)).thenReturn(employeePage);
}
问题在于您的测试用例模拟存根。你正在做一个mix of actual objects and mocked objects which is not a supported functionality in Mockito
.您可以使用 all real objects
或 all mocked objects
.
在您的测试用例中
when(Utils.sort(pageable, anyInt(), anyInt(), anyString(), anyString())).thenReturn(pageableMock);
pageable
是一个实际对象,其余对象是模拟实例。
将其替换为以下内容以将所有模拟实例用于模拟调用,如下所示
when(Utils.sort(any(Pageable.class), anyInt(), anyInt(), anyString(), anyString())).thenReturn(pageableMock);