重现步骤(如果有就写完整)
单元测试代码:
/**
* @author liuly
* @since 2024-04-22 17:23
*/
@ExtendWith(MockitoExtension.class)
class AdminEventServiceImplTestOne {
@Mock
private JpaBase jpaBase ;
@Mock
EntityManager entityManager;
@Mock
private JPAQueryFactory jpa ;
@Mock
private JPAQuery jpaQuery;
@InjectMocks
private AdminEventServiceImpl yourService;
private List<ClusterEventListVo> expectedEntities;
private ClusterEventListQo qo;
@BeforeEach
public void setup() {
expectedEntities =Arrays.asList(new ClusterEventListVo(), new ClusterEventListVo());
qo = new ClusterEventListQo();
qo.setClusterId(0L);
qo.setServiceType(DeployServiceType.Graph);
PageQo pageQo = new PageQo();
pageQo.setPageNo(1);
pageQo.setPageSize(10);
when(jpa.select(any(Expression.class))).thenReturn(jpaQuery);
doReturn(jpaQuery).when(jpaQuery).from(any(EntityPath.class));
when(jpaQuery.where(any(Predicate.class))).thenReturn(jpaQuery);
doReturn(jpaQuery).when(jpaQuery).orderBy(any(OrderSpecifier.class));
when(jpaQuery.limit(anyLong())).thenReturn(jpaQuery);
when(jpaQuery.offset(anyLong())).thenReturn(jpaQuery);
when(jpaQuery.fetch()).thenReturn(expectedEntities);
}
@Test
public void testFindClusterEventList2() {
PageResponse<ClusterEventListVo> result= yourService.findClusterEventList(qo);
assertNotNull(result, "The result should not be null");
assertEquals(expectedEntities.size(), result.getPayload().getTotal(), "The size of the result list should be equal to the expected list");
}
}
被测试业务service实现类方法:
@Slf4j
@Service
public class AdminEventServiceImpl extends JpaBase implements AdminEventService {
private static ExecutorService executorService = new ThreadPoolExecutor(4, 8, 60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2096), new ThreadPoolExecutor.CallerRunsPolicy());
@Autowired
private AdminClusterEventDao adminClusterEventDao;
@Override
public PageResponse<ClusterEventListVo> findClusterEventList(ClusterEventListQo qo) {
QAdminClusterEventPo adminClusterEventTable = QAdminClusterEventPo.adminClusterEventPo;
BooleanBuilder builder = buildClusterEventListQueryCondition(qo, adminClusterEventTable);
PageQo pageQo = qo.getPage();
List<OrderSpecifier> orderSpecifiers = buildClusterEventSortCondition(pageQo, adminClusterEventTable);
JPAQuery<ClusterEventListVo> jpaQuery = jpa.select(Projections.bean(ClusterEventListVo.class,
adminClusterEventTable.id.as("id"),
adminClusterEventTable.eventType.as("eventType"),
adminClusterEventTable.eventName.as("eventName"),
adminClusterEventTable.serviceType.as("serviceType"),
adminClusterEventTable.namespace.as("namespace"),
adminClusterEventTable.hostName.as("hostName"),
adminClusterEventTable.ip.as("ip"),
adminClusterEventTable.resultType.as("resultType"),
adminClusterEventTable.firstHappenTime.as("happenTime"),
adminClusterEventTable.happenCount.as("happenCount"),
adminClusterEventTable.operator.as("operator"),
adminClusterEventTable.eventDetail.as("eventDetail")
)).from(adminClusterEventTable)
.where(builder);
List<ClusterEventListVo> clusterEventListVos = jpaQuery.orderBy(orderSpecifiers.toArray(new OrderSpecifier[]{}))
.offset(pageQo.getPageSize() * (pageQo.getPageNo() - 1L))
.limit(pageQo.getPageSize()).fetch();
if (CollectionUtils.isEmpty(clusterEventListVos)) {
return PageResponse.success(Collections.emptyList(), 0L, pageQo);
}
long total = jpaQuery.fetchCount();
return PageResponse.success(clusterEventListVos, total, pageQo);
}
}
当前service继承的父类:和jpa有关
@Slf4j
@NoRepositoryBean
public class JpaBase {
@Autowired
@PersistenceContext
private EntityManager entityManager;
protected JPAQueryFactory jpa;
@Value("${batch.size:1000}")
private int batchSize;
@Resource
private DataSourceProperties dataSourceProperties;
@PostConstruct
public void initFactory() {
jpa = new JPAQueryFactory(entityManager);
}
protected <T extends BasePo> void setUpdateBy(T bean, String userId) {
if (Objects.isNull(bean.getId()) || StringUtils.isBlank(bean.getCreatedBy())) {
bean.setCreatedBy(userId);
}
bean.setUpdatedBy(userId);
}
public Expression buildExpression(Object path) {
if (!(path instanceof Path) || !(path instanceof DslExpression)) {
return null;
}
return ((DslExpression) path).as(((Path) path).getMetadata().getName());
}
public Expression buildExpression(Object path, String alias) {
if (!(path instanceof Path) || !(path instanceof DslExpression)) {
return null;
}
return ((DslExpression) path).as(alias);
}
/**
* get entity's table name
*
* @param poCls
* @param <E>
* @return
*/
public <E> String getPoTableName(Class<E> poCls) {
Table annotation = poCls.getAnnotation(Table.class);
return annotation.name();
}
/**
* get entity's sequence name
*
* @param poCls
* @param <E>
* @return
*/
public <E> String getSequenceName(Class<E> poCls) {
Field[] fields = poCls.getDeclaredFields();
for (Field field : fields) {
GeneratedValue generatedValue = field.getAnnotation(GeneratedValue.class);
if (generatedValue != null) {
return generatedValue.generator();
}
}
return null;
}
}
idea运行控制台报错信息:
org.mockito.exceptions.misusing.PotentialStubbingProblem:
Strict stubbing argument mismatch. Please check:
- this invocation of 'orderBy' method:
jpaQuery.orderBy(
adminClusterEventPo.id DESC
);
-> at com.haizhi.admin.server.restapi.service.impl.AdminEventServiceImpl.findClusterEventList(AdminEventServiceImpl.java:89)
- has following stubbing(s) with different arguments:
1. jpaQuery.orderBy(null);
-> at com.haizhi.admin.server.restapi.service.impl.AdminEventServiceImplTestOne.setup(AdminEventServiceImplTestOne.java:73)
Typically, stubbing argument mismatch indicates user mistake when writing tests.
Mockito fails early so that you can debug potential problem easily.
However, there are legit scenarios when this exception generates false negative signal:
- stubbing the same method multiple times using 'given().will()' or 'when().then()' API
Please use 'will().given()' or 'doReturn().when()' API for stubbing.
- stubbed method is intentionally invoked with different arguments by code under test
Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).
For more information see javadoc for PotentialStubbingProblem class.
at com.haizhi.admin.server.restapi.service.impl.AdminEventServiceImpl.findClusterEventList(AdminEventServiceImpl.java:89)
at com.haizhi.admin.server.restapi.service.impl.AdminEventServiceImplTestOne.testFindClusterEventList2(AdminEventServiceImplTestOne.java:80)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
jpa可以链式生成sql语句对象,但是现在想mock这个方法,出现存根参数不匹配,主要是
doReturn(jpaQuery).when(jpaQuery).orderBy(any(OrderSpecifier.class));
我改成如下也不行
doReturn(jpaQuery).when(jpaQuery).orderBy(any(OrderSpecifier[].class));
或者针对上面的业务类AdminEventServiceImpl 的findClusterEventList方法,如何写一个单元测试,感谢解答!!!
New contributor
luyang liu is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.