feat: 1.3.0
1. 添加测试用例 2. 优化代码
This commit is contained in:
parent
ddfe1a2ce2
commit
c16f8e977f
@ -1,4 +1,4 @@
|
|||||||
package com.aizuda.easy.retry.client.core.report;
|
package com.aizuda.easy.retry.client.core;
|
||||||
|
|
||||||
import com.aizuda.easy.retry.client.core.retryer.RetryerInfo;
|
import com.aizuda.easy.retry.client.core.retryer.RetryerInfo;
|
||||||
|
|
@ -14,18 +14,19 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author: www.byteblogs.com
|
* @author: www.byteblogs.com
|
||||||
* @date : 2021-11-19 19:00
|
* @date : 2021-11-19 19:00
|
||||||
|
* @since 1.0.0
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class EndListener implements ApplicationListener<ContextClosedEvent> {
|
public class EasyRetryEndListener implements ApplicationListener<ContextClosedEvent> {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private List<Lifecycle> lifecycleList;
|
private List<Lifecycle> lifecycleList;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(ContextClosedEvent event) {
|
public void onApplicationEvent(ContextClosedEvent event) {
|
||||||
log.info("EASY-RETRY-CLIENT 关闭");
|
log.info("Easy-Retry client about to shutdown");
|
||||||
lifecycleList.forEach(Lifecycle::close);
|
lifecycleList.forEach(Lifecycle::close);
|
||||||
log.info("EASY-RETRY-CLIENT 关闭成功");
|
log.info("Easy-Retry client closed successfully");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,15 +17,15 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class StartListener implements ApplicationRunner {
|
public class EasyRetryStartListener implements ApplicationRunner {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private List<Lifecycle> lifecycleList;
|
private List<Lifecycle> lifecycleList;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ApplicationArguments args) throws Exception {
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
log.info("EASY-RETRY-CLIENT-RETRY 启动");
|
log.info("Easy-Retry client is preparing to start");
|
||||||
lifecycleList.forEach(Lifecycle::start);
|
lifecycleList.forEach(Lifecycle::start);
|
||||||
log.info("EASY-RETRY-CLIENT-RETRY 启动成功");
|
log.info("Easy-Retry client started successfully");
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ package com.aizuda.easy.retry.client.core.report;
|
|||||||
|
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import com.aizuda.easy.retry.client.core.IdempotentIdGenerate;
|
import com.aizuda.easy.retry.client.core.IdempotentIdGenerate;
|
||||||
|
import com.aizuda.easy.retry.client.core.Report;
|
||||||
import com.aizuda.easy.retry.client.core.RetryArgSerializer;
|
import com.aizuda.easy.retry.client.core.RetryArgSerializer;
|
||||||
import com.aizuda.easy.retry.client.core.cache.RetryerInfoCache;
|
import com.aizuda.easy.retry.client.core.cache.RetryerInfoCache;
|
||||||
import com.aizuda.easy.retry.client.core.config.EasyRetryProperties;
|
import com.aizuda.easy.retry.client.core.config.EasyRetryProperties;
|
||||||
@ -9,7 +10,6 @@ import com.aizuda.easy.retry.client.core.exception.EasyRetryClientException;
|
|||||||
import com.aizuda.easy.retry.client.core.intercepter.RetrySiteSnapshot;
|
import com.aizuda.easy.retry.client.core.intercepter.RetrySiteSnapshot;
|
||||||
import com.aizuda.easy.retry.client.core.retryer.RetryerInfo;
|
import com.aizuda.easy.retry.client.core.retryer.RetryerInfo;
|
||||||
import com.aizuda.easy.retry.client.core.spel.SPELParamFunction;
|
import com.aizuda.easy.retry.client.core.spel.SPELParamFunction;
|
||||||
import com.aizuda.easy.retry.client.core.window.RetryLeapArray;
|
|
||||||
import com.aizuda.easy.retry.common.core.log.LogUtils;
|
import com.aizuda.easy.retry.common.core.log.LogUtils;
|
||||||
import com.aizuda.easy.retry.server.model.dto.RetryTaskDTO;
|
import com.aizuda.easy.retry.server.model.dto.RetryTaskDTO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -18,14 +18,14 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
|||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 上报抽象类
|
||||||
|
*
|
||||||
* @author www.byteblogs.com
|
* @author www.byteblogs.com
|
||||||
* @date 2023-05-15
|
* @date 2023-05-15
|
||||||
* @since 2.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public abstract class AbstractReport implements Report {
|
public abstract class AbstractReport implements Report {
|
||||||
@ -34,9 +34,9 @@ public abstract class AbstractReport implements Report {
|
|||||||
@Qualifier("easyRetryJacksonSerializer")
|
@Qualifier("easyRetryJacksonSerializer")
|
||||||
private RetryArgSerializer retryArgSerializer;
|
private RetryArgSerializer retryArgSerializer;
|
||||||
|
|
||||||
public static final int SAMPLE_COUNT = 10;
|
protected static final int SAMPLE_COUNT = 10;
|
||||||
|
|
||||||
public static final int INTERVAL_IN_MS = 1000;
|
protected static final int INTERVAL_IN_MS = 1000;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean report(String scene, final String targetClassName, final Object[] params) {
|
public boolean report(String scene, final String targetClassName, final Object[] params) {
|
||||||
@ -44,7 +44,7 @@ public abstract class AbstractReport implements Report {
|
|||||||
Assert.notNull(retryerInfo, () -> new EasyRetryClientException("retryerInfo is null"));
|
Assert.notNull(retryerInfo, () -> new EasyRetryClientException("retryerInfo is null"));
|
||||||
|
|
||||||
if (RetrySiteSnapshot.getStage().equals(RetrySiteSnapshot.EnumStage.REMOTE.getStage()) && !retryerInfo.isForceReport()) {
|
if (RetrySiteSnapshot.getStage().equals(RetrySiteSnapshot.EnumStage.REMOTE.getStage()) && !retryerInfo.isForceReport()) {
|
||||||
LogUtils.info(log, "已经上报成功,无需重复上报 scene:[{}] targetClassName:[{}] args:[{}]",
|
LogUtils.info(log, "Successfully reported, no need to repeat reporting. scene:[{}] targetClassName:[{}] args:[{}]",
|
||||||
retryerInfo.getScene(), retryerInfo.getExecutorClassName(), params);
|
retryerInfo.getScene(), retryerInfo.getExecutorClassName(), params);
|
||||||
return Boolean.TRUE;
|
return Boolean.TRUE;
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,19 @@
|
|||||||
package com.aizuda.easy.retry.client.core.report;
|
package com.aizuda.easy.retry.client.core.report;
|
||||||
|
|
||||||
import com.aizuda.easy.retry.client.core.Lifecycle;
|
import com.aizuda.easy.retry.client.core.Lifecycle;
|
||||||
import com.aizuda.easy.retry.client.core.client.NettyClient;
|
|
||||||
import com.aizuda.easy.retry.client.core.client.proxy.RequestBuilder;
|
|
||||||
import com.aizuda.easy.retry.client.core.retryer.RetryerInfo;
|
import com.aizuda.easy.retry.client.core.retryer.RetryerInfo;
|
||||||
import com.aizuda.easy.retry.client.core.window.RetryLeapArray;
|
import com.aizuda.easy.retry.client.core.window.RetryLeapArray;
|
||||||
import com.aizuda.easy.retry.common.core.log.LogUtils;
|
|
||||||
import com.aizuda.easy.retry.common.core.model.NettyResult;
|
|
||||||
import com.aizuda.easy.retry.common.core.util.JsonUtil;
|
|
||||||
import com.aizuda.easy.retry.server.model.dto.RetryTaskDTO;
|
import com.aizuda.easy.retry.server.model.dto.RetryTaskDTO;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 异步上报数据
|
||||||
|
*
|
||||||
* @author www.byteblogs.com
|
* @author www.byteblogs.com
|
||||||
* @date 2023-05-15
|
* @date 2023-05-15
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
@ -62,8 +58,8 @@ public class AsyncReport extends AbstractReport implements Lifecycle {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
log.info("reportHandler about to shutdown");
|
log.info("AsyncReport about to shutdown");
|
||||||
slidingWindow.currentWindow();
|
slidingWindow.currentWindow();
|
||||||
log.info("reportHandler has been shutdown");
|
log.info("AsyncReport has been shutdown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,8 @@ import java.util.Collections;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 同步上报数据
|
||||||
|
*
|
||||||
* @author www.byteblogs.com
|
* @author www.byteblogs.com
|
||||||
* @date 2023-05-15
|
* @date 2023-05-15
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
@ -42,14 +44,14 @@ public class SyncReport extends AbstractReport {
|
|||||||
|
|
||||||
RetryTaskDTO retryTaskDTO = buildRetryTaskDTO(scene, targetClassName, args);
|
RetryTaskDTO retryTaskDTO = buildRetryTaskDTO(scene, targetClassName, args);
|
||||||
|
|
||||||
NettyClient CLIENT = RequestBuilder.<NettyClient, NettyResult>newBuilder()
|
NettyClient client = RequestBuilder.<NettyClient, NettyResult>newBuilder()
|
||||||
.client(NettyClient.class)
|
.client(NettyClient.class)
|
||||||
.async(Boolean.FALSE)
|
.async(Boolean.FALSE)
|
||||||
.timeout(timeout)
|
.timeout(timeout)
|
||||||
.unit(unit)
|
.unit(unit)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
NettyResult result = CLIENT.reportRetryInfo(Collections.singletonList(retryTaskDTO));
|
NettyResult result = client.reportRetryInfo(Collections.singletonList(retryTaskDTO));
|
||||||
LogUtils.debug(log, "Data report result result:[{}]", JsonUtil.toJsonString(result));
|
LogUtils.debug(log, "Data report result result:[{}]", JsonUtil.toJsonString(result));
|
||||||
|
|
||||||
return (Boolean) result.getData();
|
return (Boolean) result.getData();
|
||||||
|
@ -4,7 +4,7 @@ import com.aizuda.easy.retry.client.core.RetryExecutor;
|
|||||||
import com.aizuda.easy.retry.client.core.RetryExecutorParameter;
|
import com.aizuda.easy.retry.client.core.RetryExecutorParameter;
|
||||||
import com.aizuda.easy.retry.client.core.event.EasyRetryListener;
|
import com.aizuda.easy.retry.client.core.event.EasyRetryListener;
|
||||||
import com.aizuda.easy.retry.client.core.intercepter.RetrySiteSnapshot;
|
import com.aizuda.easy.retry.client.core.intercepter.RetrySiteSnapshot;
|
||||||
import com.aizuda.easy.retry.client.core.report.Report;
|
import com.aizuda.easy.retry.client.core.Report;
|
||||||
import com.github.rholder.retry.Retryer;
|
import com.github.rholder.retry.Retryer;
|
||||||
import com.github.rholder.retry.StopStrategy;
|
import com.github.rholder.retry.StopStrategy;
|
||||||
import com.github.rholder.retry.WaitStrategy;
|
import com.github.rholder.retry.WaitStrategy;
|
||||||
|
@ -9,6 +9,8 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -12,7 +12,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
* @date : 2022-03-07 14:07
|
* @date : 2022-03-07 14:07
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@ExecutorMethodRegister(scene = CustomAsyncCreateTask.SCENE, async = true)
|
@ExecutorMethodRegister(scene = CustomAsyncCreateTask.SCENE, async = true, forceReport = true)
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class CustomAsyncCreateTask implements ExecutorMethod {
|
public class CustomAsyncCreateTask implements ExecutorMethod {
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
* @date : 2022-03-07 14:07
|
* @date : 2022-03-07 14:07
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@ExecutorMethodRegister(scene = CustomSyncCreateTask.SCENE, async = false, timeout = 10000, unit = TimeUnit.MILLISECONDS, forceReport = false)
|
@ExecutorMethodRegister(scene = CustomSyncCreateTask.SCENE, async = false, timeout = 10000, unit = TimeUnit.MILLISECONDS, forceReport = true)
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class CustomSyncCreateTask implements ExecutorMethod {
|
public class CustomSyncCreateTask implements ExecutorMethod {
|
||||||
|
|
||||||
|
@ -2,8 +2,11 @@ package com.example.demo;
|
|||||||
|
|
||||||
import com.aizuda.easy.retry.client.core.annotation.Retryable;
|
import com.aizuda.easy.retry.client.core.annotation.Retryable;
|
||||||
import com.aizuda.easy.retry.client.core.exception.EasyRetryClientException;
|
import com.aizuda.easy.retry.client.core.exception.EasyRetryClientException;
|
||||||
|
import com.aizuda.easy.retry.client.core.intercepter.RetrySiteSnapshot;
|
||||||
|
import com.aizuda.easy.retry.client.core.intercepter.RetrySiteSnapshot.EnumStage;
|
||||||
import com.aizuda.easy.retry.client.core.retryer.EasyRetryTemplate;
|
import com.aizuda.easy.retry.client.core.retryer.EasyRetryTemplate;
|
||||||
import com.aizuda.easy.retry.client.core.retryer.RetryTaskTemplateBuilder;
|
import com.aizuda.easy.retry.client.core.retryer.RetryTaskTemplateBuilder;
|
||||||
|
import com.aizuda.easy.retry.common.core.model.Result;
|
||||||
import com.example.model.Zoo;
|
import com.example.model.Zoo;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -22,6 +25,8 @@ public class NestMethodService {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TestExistsTransactionalRetryService testExistsTransactionalRetryService;
|
private TestExistsTransactionalRetryService testExistsTransactionalRetryService;
|
||||||
|
@Autowired
|
||||||
|
private RemoteService remoteService;
|
||||||
|
|
||||||
@Retryable(scene = "testNestMethod" , isThrowException = false)
|
@Retryable(scene = "testNestMethod" , isThrowException = false)
|
||||||
@Transactional
|
@Transactional
|
||||||
@ -33,12 +38,11 @@ public class NestMethodService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public void testNestMethodForCustomSyncCreateTask() {
|
public void testNestMethodForCustomSyncCreateTask() {
|
||||||
|
|
||||||
Random random = new Random();
|
if (RetrySiteSnapshot.getStage() == null || RetrySiteSnapshot.getStage() == EnumStage.LOCAL.getStage()) {
|
||||||
int i = random.nextInt(5);
|
|
||||||
if (i <= 2) {
|
|
||||||
throw new EasyRetryClientException("测试注解重试和手动重试");
|
throw new EasyRetryClientException("测试注解重试和手动重试");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 同步强制上报
|
||||||
Zoo zoo = new Zoo();
|
Zoo zoo = new Zoo();
|
||||||
zoo.setNow(LocalDateTime.now());
|
zoo.setNow(LocalDateTime.now());
|
||||||
EasyRetryTemplate retryTemplate = RetryTaskTemplateBuilder.newBuilder()
|
EasyRetryTemplate retryTemplate = RetryTaskTemplateBuilder.newBuilder()
|
||||||
@ -48,5 +52,14 @@ public class NestMethodService {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
retryTemplate.executeRetry();
|
retryTemplate.executeRetry();
|
||||||
|
|
||||||
|
// 异步强制上报
|
||||||
|
zoo.setNow(LocalDateTime.now());
|
||||||
|
retryTemplate = RetryTaskTemplateBuilder.newBuilder()
|
||||||
|
.withExecutorMethod(CustomAsyncCreateTask.class)
|
||||||
|
.withParam(zoo)
|
||||||
|
.withScene(CustomAsyncCreateTask.SCENE)
|
||||||
|
.build();
|
||||||
|
retryTemplate.executeRetry();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ public class RemoteService {
|
|||||||
private RestTemplate restTemplate;
|
private RestTemplate restTemplate;
|
||||||
|
|
||||||
public Result call() {
|
public Result call() {
|
||||||
return restTemplate.getForObject("http://127.0.0.1:8088/school/id", Result.class);
|
return restTemplate.getForObject("http://127.0.0.1:8089/school/id", Result.class);
|
||||||
// return new Result();
|
// return new Result();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,8 +55,8 @@ public class TestExistsTransactionalRetryService {
|
|||||||
throw new UnsupportedOperationException("调用远程失败" + school.getAddress());
|
throw new UnsupportedOperationException("调用远程失败" + school.getAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionalEvent<String> event = new TransactionalEvent<>("123");
|
// TransactionalEvent<String> event = new TransactionalEvent<>("123");
|
||||||
SpringContext.CONTEXT.publishEvent(event);
|
// SpringContext.CONTEXT.publishEvent(event);
|
||||||
|
|
||||||
return "testSimpleInsert"+school.getAddress();
|
return "testSimpleInsert"+school.getAddress();
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,22 @@ package com.example;
|
|||||||
|
|
||||||
import com.aizuda.easy.retry.client.core.retryer.EasyRetryTemplate;
|
import com.aizuda.easy.retry.client.core.retryer.EasyRetryTemplate;
|
||||||
import com.aizuda.easy.retry.client.core.retryer.RetryTaskTemplateBuilder;
|
import com.aizuda.easy.retry.client.core.retryer.RetryTaskTemplateBuilder;
|
||||||
|
import com.aizuda.easy.retry.common.core.model.Result;
|
||||||
import com.example.demo.CustomAsyncCreateTask;
|
import com.example.demo.CustomAsyncCreateTask;
|
||||||
import com.example.demo.CustomSyncCreateTask;
|
import com.example.demo.CustomSyncCreateTask;
|
||||||
import com.example.demo.NestMethodService;
|
import com.example.demo.NestMethodService;
|
||||||
|
import com.example.demo.RemoteService;
|
||||||
import com.example.model.Cat;
|
import com.example.model.Cat;
|
||||||
import com.example.model.Zoo;
|
import com.example.model.Zoo;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author: www.byteblogs.com
|
* @author: www.byteblogs.com
|
||||||
@ -24,6 +29,8 @@ public class EasyRetryTemplateTest {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private NestMethodService nestMethodService;
|
private NestMethodService nestMethodService;
|
||||||
|
@MockBean
|
||||||
|
private RemoteService remoteService;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void generateAsyncTaskTest() throws InterruptedException {
|
public void generateAsyncTaskTest() throws InterruptedException {
|
||||||
|
@ -39,7 +39,7 @@ public class ExistsTransactionalRetryServiceTest {
|
|||||||
Mockito.when(remoteService.call())
|
Mockito.when(remoteService.call())
|
||||||
.thenReturn(new Result(0, "1"))
|
.thenReturn(new Result(0, "1"))
|
||||||
.thenReturn(new Result(0, "2"))
|
.thenReturn(new Result(0, "2"))
|
||||||
.thenReturn(new Result(3, "3"))
|
.thenReturn(new Result(0, "3"))
|
||||||
.thenReturn(new Result(0, "4"))
|
.thenReturn(new Result(0, "4"))
|
||||||
.thenReturn(new Result(0, "5"))
|
.thenReturn(new Result(0, "5"))
|
||||||
;
|
;
|
||||||
|
Loading…
Reference in New Issue
Block a user