Merge remote-tracking branch 'origin/master'
commit
655d96ff26
@ -0,0 +1,103 @@
|
||||
package com.yau.digitalrmb.exchange.application.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsEntity;
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsMapper;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.UUID;
|
||||
|
||||
/** 数字货币兑换模块的错误次数、进度和成绩统计。 */
|
||||
@Service
|
||||
public class ExchangeScoreService {
|
||||
public static final String MODULE_NAME = "数字货币兑换";
|
||||
private static final int MODULE_SERIAL_NUMBER = 4;
|
||||
private static final int TOTAL_STEPS = 5;
|
||||
private static final double TOTAL_SCORE = 100.0;
|
||||
|
||||
@Resource
|
||||
private StuModuleScoreDetailsMapper scoreDetailsMapper;
|
||||
|
||||
@Value("${exchange.score.wrong-deduct:0.50}")
|
||||
private BigDecimal wrongDeduct = new BigDecimal("0.50");
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public int recordError(String userId) {
|
||||
if (blank(userId)) return 0;
|
||||
StuModuleScoreDetailsEntity detail = getOrCreate(userId);
|
||||
int errors = errorCount(detail.getCompletionStatus()) + 1;
|
||||
detail.setCompletionStatus(String.valueOf(errors));
|
||||
detail.setScoreProject(score(errors, progress(detail.getSchedule())));
|
||||
scoreDetailsMapper.updateById(detail);
|
||||
return errors;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void markStepCompleted(String userId, int completedStep) {
|
||||
if (blank(userId)) return;
|
||||
StuModuleScoreDetailsEntity detail = getOrCreate(userId);
|
||||
int errors = errorCount(detail.getCompletionStatus());
|
||||
int normalized = Math.max(0, Math.min(TOTAL_STEPS, completedStep));
|
||||
double completedSchedule = BigDecimal.valueOf(normalized)
|
||||
.multiply(BigDecimal.valueOf(TOTAL_SCORE))
|
||||
.divide(BigDecimal.valueOf(TOTAL_STEPS), 2, RoundingMode.HALF_UP)
|
||||
.doubleValue();
|
||||
double schedule = Math.max(progress(detail.getSchedule()), completedSchedule);
|
||||
detail.setCompletionStatus(String.valueOf(errors));
|
||||
detail.setSchedule(schedule);
|
||||
detail.setScoreProject(score(errors, schedule));
|
||||
scoreDetailsMapper.updateById(detail);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public StuModuleScoreDetailsEntity detail(String userId) {
|
||||
if (blank(userId)) return null;
|
||||
return scoreDetailsMapper.selectOne(new LambdaQueryWrapper<StuModuleScoreDetailsEntity>()
|
||||
.eq(StuModuleScoreDetailsEntity::getUserId, userId)
|
||||
.eq(StuModuleScoreDetailsEntity::getMoudule, MODULE_NAME)
|
||||
.eq(StuModuleScoreDetailsEntity::getSerialNumber, MODULE_SERIAL_NUMBER)
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
private StuModuleScoreDetailsEntity getOrCreate(String userId) {
|
||||
StuModuleScoreDetailsEntity existing = detail(userId);
|
||||
if (existing != null) return existing;
|
||||
StuModuleScoreDetailsEntity created = new StuModuleScoreDetailsEntity();
|
||||
created.setId(UUID.randomUUID().toString());
|
||||
created.setMoudule(MODULE_NAME);
|
||||
created.setLearningProjects("实验实训");
|
||||
created.setAssessmentItems("兑换流程错误次数");
|
||||
created.setScoringCriteria(wrongDeduct.stripTrailingZeros().toPlainString());
|
||||
created.setCompletionStatus("0");
|
||||
created.setScoreProject(0.0);
|
||||
created.setUserId(userId);
|
||||
created.setTotalScore(TOTAL_SCORE);
|
||||
created.setSerialNumber(MODULE_SERIAL_NUMBER);
|
||||
created.setSchedule(0.0);
|
||||
scoreDetailsMapper.insert(created);
|
||||
return created;
|
||||
}
|
||||
|
||||
private double score(int errors, double schedule) {
|
||||
BigDecimal base = BigDecimal.valueOf(TOTAL_SCORE)
|
||||
.subtract(wrongDeduct.multiply(BigDecimal.valueOf(Math.max(0, errors))))
|
||||
.max(BigDecimal.ZERO);
|
||||
return base.multiply(BigDecimal.valueOf(schedule))
|
||||
.divide(BigDecimal.valueOf(TOTAL_SCORE), 2, RoundingMode.HALF_UP)
|
||||
.doubleValue();
|
||||
}
|
||||
|
||||
private double progress(Double schedule) { return schedule == null ? 0.0 : schedule; }
|
||||
private int errorCount(String value) {
|
||||
if (blank(value)) return 0;
|
||||
try { return Math.max(0, Integer.parseInt(value)); }
|
||||
catch (NumberFormatException ignored) { return 0; }
|
||||
}
|
||||
private boolean blank(String value) { return value == null || value.trim().isEmpty(); }
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
package com.yau.digitalrmb.issuance.application.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsEntity;
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsMapper;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.UUID;
|
||||
|
||||
/** 发行数字货币模块的错误次数、进度和成绩统计。 */
|
||||
@Service
|
||||
public class IssuanceScoreService {
|
||||
public static final String MODULE_NAME = "发行数字货币";
|
||||
private static final int MODULE_SERIAL_NUMBER = 2;
|
||||
private static final int TOTAL_STEPS = 7;
|
||||
private static final double TOTAL_SCORE = 100.0;
|
||||
|
||||
@Resource
|
||||
private StuModuleScoreDetailsMapper scoreDetailsMapper;
|
||||
|
||||
@Value("${issuance.score.wrong-deduct:0.50}")
|
||||
private BigDecimal wrongDeduct = new BigDecimal("0.50");
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public int recordError(String userId) {
|
||||
if (blank(userId)) return 0;
|
||||
StuModuleScoreDetailsEntity detail = getOrCreate(userId);
|
||||
int errors = errorCount(detail.getCompletionStatus()) + 1;
|
||||
detail.setCompletionStatus(String.valueOf(errors));
|
||||
detail.setScoreProject(score(errors, progress(detail.getSchedule())));
|
||||
scoreDetailsMapper.updateById(detail);
|
||||
return errors;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void markStepCompleted(String userId, int completedStep) {
|
||||
if (blank(userId)) return;
|
||||
StuModuleScoreDetailsEntity detail = getOrCreate(userId);
|
||||
int errors = errorCount(detail.getCompletionStatus());
|
||||
int normalized = Math.max(0, Math.min(TOTAL_STEPS, completedStep));
|
||||
double completedSchedule = BigDecimal.valueOf(normalized)
|
||||
.multiply(BigDecimal.valueOf(TOTAL_SCORE))
|
||||
.divide(BigDecimal.valueOf(TOTAL_STEPS), 2, RoundingMode.HALF_UP)
|
||||
.doubleValue();
|
||||
double schedule = Math.max(progress(detail.getSchedule()), completedSchedule);
|
||||
detail.setCompletionStatus(String.valueOf(errors));
|
||||
detail.setSchedule(schedule);
|
||||
detail.setScoreProject(score(errors, schedule));
|
||||
scoreDetailsMapper.updateById(detail);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public StuModuleScoreDetailsEntity detail(String userId) {
|
||||
if (blank(userId)) return null;
|
||||
return scoreDetailsMapper.selectOne(new LambdaQueryWrapper<StuModuleScoreDetailsEntity>()
|
||||
.eq(StuModuleScoreDetailsEntity::getUserId, userId)
|
||||
.eq(StuModuleScoreDetailsEntity::getMoudule, MODULE_NAME)
|
||||
.eq(StuModuleScoreDetailsEntity::getSerialNumber, MODULE_SERIAL_NUMBER)
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
private StuModuleScoreDetailsEntity getOrCreate(String userId) {
|
||||
StuModuleScoreDetailsEntity existing = detail(userId);
|
||||
if (existing != null) return existing;
|
||||
StuModuleScoreDetailsEntity created = new StuModuleScoreDetailsEntity();
|
||||
created.setId(UUID.randomUUID().toString());
|
||||
created.setMoudule(MODULE_NAME);
|
||||
created.setLearningProjects("实验实训");
|
||||
created.setAssessmentItems("发行流程错误次数");
|
||||
created.setScoringCriteria(wrongDeduct.stripTrailingZeros().toPlainString());
|
||||
created.setCompletionStatus("0");
|
||||
created.setScoreProject(0.0);
|
||||
created.setUserId(userId);
|
||||
created.setTotalScore(TOTAL_SCORE);
|
||||
created.setSerialNumber(MODULE_SERIAL_NUMBER);
|
||||
created.setSchedule(0.0);
|
||||
scoreDetailsMapper.insert(created);
|
||||
return created;
|
||||
}
|
||||
|
||||
private double score(int errors, double schedule) {
|
||||
BigDecimal base = BigDecimal.valueOf(TOTAL_SCORE)
|
||||
.subtract(wrongDeduct.multiply(BigDecimal.valueOf(Math.max(0, errors))))
|
||||
.max(BigDecimal.ZERO);
|
||||
return base.multiply(BigDecimal.valueOf(schedule))
|
||||
.divide(BigDecimal.valueOf(TOTAL_SCORE), 2, RoundingMode.HALF_UP)
|
||||
.doubleValue();
|
||||
}
|
||||
|
||||
private double progress(Double schedule) { return schedule == null ? 0.0 : schedule; }
|
||||
|
||||
private int errorCount(String value) {
|
||||
if (blank(value)) return 0;
|
||||
try { return Math.max(0, Integer.parseInt(value)); }
|
||||
catch (NumberFormatException ignored) { return 0; }
|
||||
}
|
||||
|
||||
private boolean blank(String value) { return value == null || value.trim().isEmpty(); }
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
package com.yau.digitalrmb.payment.application.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsEntity;
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsMapper;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.UUID;
|
||||
|
||||
/** 用户支付数字货币模块的错误次数、进度和成绩统计。 */
|
||||
@Service
|
||||
public class PaymentScoreService {
|
||||
public static final String MODULE_NAME = "用户支付数字货币";
|
||||
private static final int MODULE_SERIAL_NUMBER = 5;
|
||||
private static final int TOTAL_STEPS = 6;
|
||||
private static final double TOTAL_SCORE = 100.0;
|
||||
|
||||
@Resource
|
||||
private StuModuleScoreDetailsMapper scoreDetailsMapper;
|
||||
|
||||
@Value("${payment.score.wrong-deduct:0.50}")
|
||||
private BigDecimal wrongDeduct = new BigDecimal("0.50");
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public int recordError(String userId) {
|
||||
if (blank(userId)) return 0;
|
||||
StuModuleScoreDetailsEntity detail = getOrCreate(userId);
|
||||
int errors = errorCount(detail.getCompletionStatus()) + 1;
|
||||
detail.setCompletionStatus(String.valueOf(errors));
|
||||
detail.setScoreProject(score(errors, progress(detail.getSchedule())));
|
||||
scoreDetailsMapper.updateById(detail);
|
||||
return errors;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void markStepCompleted(String userId, int completedStep) {
|
||||
if (blank(userId)) return;
|
||||
StuModuleScoreDetailsEntity detail = getOrCreate(userId);
|
||||
int errors = errorCount(detail.getCompletionStatus());
|
||||
int normalized = Math.max(0, Math.min(TOTAL_STEPS, completedStep));
|
||||
double completedSchedule = BigDecimal.valueOf(normalized)
|
||||
.multiply(BigDecimal.valueOf(TOTAL_SCORE))
|
||||
.divide(BigDecimal.valueOf(TOTAL_STEPS), 2, RoundingMode.HALF_UP)
|
||||
.doubleValue();
|
||||
double schedule = Math.max(progress(detail.getSchedule()), completedSchedule);
|
||||
detail.setCompletionStatus(String.valueOf(errors));
|
||||
detail.setSchedule(schedule);
|
||||
detail.setScoreProject(score(errors, schedule));
|
||||
scoreDetailsMapper.updateById(detail);
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public StuModuleScoreDetailsEntity detail(String userId) {
|
||||
if (blank(userId)) return null;
|
||||
return scoreDetailsMapper.selectOne(new LambdaQueryWrapper<StuModuleScoreDetailsEntity>()
|
||||
.eq(StuModuleScoreDetailsEntity::getUserId, userId)
|
||||
.eq(StuModuleScoreDetailsEntity::getMoudule, MODULE_NAME)
|
||||
.eq(StuModuleScoreDetailsEntity::getSerialNumber, MODULE_SERIAL_NUMBER)
|
||||
.last("LIMIT 1"));
|
||||
}
|
||||
|
||||
private StuModuleScoreDetailsEntity getOrCreate(String userId) {
|
||||
StuModuleScoreDetailsEntity existing = detail(userId);
|
||||
if (existing != null) return existing;
|
||||
StuModuleScoreDetailsEntity created = new StuModuleScoreDetailsEntity();
|
||||
created.setId(UUID.randomUUID().toString());
|
||||
created.setMoudule(MODULE_NAME);
|
||||
created.setLearningProjects("实验实训");
|
||||
created.setAssessmentItems("支付流程错误次数");
|
||||
created.setScoringCriteria(wrongDeduct.stripTrailingZeros().toPlainString());
|
||||
created.setCompletionStatus("0");
|
||||
created.setScoreProject(0.0);
|
||||
created.setUserId(userId);
|
||||
created.setTotalScore(TOTAL_SCORE);
|
||||
created.setSerialNumber(MODULE_SERIAL_NUMBER);
|
||||
created.setSchedule(0.0);
|
||||
scoreDetailsMapper.insert(created);
|
||||
return created;
|
||||
}
|
||||
|
||||
private double score(int errors, double schedule) {
|
||||
BigDecimal base = BigDecimal.valueOf(TOTAL_SCORE)
|
||||
.subtract(wrongDeduct.multiply(BigDecimal.valueOf(Math.max(0, errors))))
|
||||
.max(BigDecimal.ZERO);
|
||||
return base.multiply(BigDecimal.valueOf(schedule))
|
||||
.divide(BigDecimal.valueOf(TOTAL_SCORE), 2, RoundingMode.HALF_UP)
|
||||
.doubleValue();
|
||||
}
|
||||
|
||||
private double progress(Double schedule) { return schedule == null ? 0.0 : schedule; }
|
||||
|
||||
private int errorCount(String value) {
|
||||
if (blank(value)) return 0;
|
||||
try { return Math.max(0, Integer.parseInt(value)); }
|
||||
catch (NumberFormatException ignored) { return 0; }
|
||||
}
|
||||
|
||||
private boolean blank(String value) { return value == null || value.trim().isEmpty(); }
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
package com.yau.digitalrmb.shared.exception;
|
||||
|
||||
import com.yau.digitalrmb.shared.api.ErrorCode;
|
||||
|
||||
/** 用户在实训动作中提交的业务输入不合法;此类错误需要计入模块成绩。 */
|
||||
public class TrainingInputException extends BusinessException {
|
||||
public TrainingInputException(String message) {
|
||||
super(ErrorCode.VALIDATION_ERROR, message);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,55 @@
|
||||
package com.yau.digitalrmb.exchange.application.service;
|
||||
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsEntity;
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ExchangeScoreServiceTest {
|
||||
@Mock private StuModuleScoreDetailsMapper mapper;
|
||||
@InjectMocks private ExchangeScoreService service;
|
||||
|
||||
@Test
|
||||
void firstErrorCreatesExchangeScoreDetail() {
|
||||
when(mapper.selectOne(any())).thenReturn(null);
|
||||
|
||||
assertEquals(1, service.recordError("user-1"));
|
||||
|
||||
ArgumentCaptor<StuModuleScoreDetailsEntity> captor =
|
||||
ArgumentCaptor.forClass(StuModuleScoreDetailsEntity.class);
|
||||
verify(mapper).insert(captor.capture());
|
||||
assertEquals("数字货币兑换", captor.getValue().getMoudule());
|
||||
assertEquals("1", captor.getValue().getCompletionStatus());
|
||||
assertEquals(4, captor.getValue().getSerialNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
void errorKeepsProgressWhenReducingScore() {
|
||||
StuModuleScoreDetailsEntity detail = new StuModuleScoreDetailsEntity();
|
||||
detail.setCompletionStatus("0");
|
||||
detail.setSchedule(100.0);
|
||||
when(mapper.selectOne(any())).thenReturn(detail);
|
||||
|
||||
assertEquals(1, service.recordError("user-1"));
|
||||
|
||||
assertEquals(99.5, detail.getScoreProject());
|
||||
verify(mapper).updateById(detail);
|
||||
}
|
||||
|
||||
@Test
|
||||
void emptyUserDoesNotWriteScore() {
|
||||
assertEquals(0, service.recordError(null));
|
||||
verify(mapper, never()).selectOne(any());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package com.yau.digitalrmb.issuance.application.service;
|
||||
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsEntity;
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class IssuanceScoreServiceTest {
|
||||
@Mock
|
||||
private StuModuleScoreDetailsMapper mapper;
|
||||
|
||||
@InjectMocks
|
||||
private IssuanceScoreService service;
|
||||
|
||||
@Test
|
||||
void firstErrorCreatesScoreDetailAndDeductsAtCurrentProgress() {
|
||||
when(mapper.selectOne(any())).thenReturn(null);
|
||||
|
||||
assertEquals(1, service.recordError("user-1"));
|
||||
|
||||
ArgumentCaptor<StuModuleScoreDetailsEntity> captor =
|
||||
ArgumentCaptor.forClass(StuModuleScoreDetailsEntity.class);
|
||||
verify(mapper).insert(captor.capture());
|
||||
StuModuleScoreDetailsEntity detail = captor.getValue();
|
||||
assertEquals("发行数字货币", detail.getMoudule());
|
||||
assertEquals("1", detail.getCompletionStatus());
|
||||
assertEquals(2, detail.getSerialNumber());
|
||||
assertEquals(0.0, detail.getScoreProject());
|
||||
}
|
||||
|
||||
@Test
|
||||
void repeatedErrorKeepsProgressAndReducesScore() {
|
||||
StuModuleScoreDetailsEntity detail = new StuModuleScoreDetailsEntity();
|
||||
detail.setCompletionStatus("1");
|
||||
detail.setSchedule(50.0);
|
||||
when(mapper.selectOne(any())).thenReturn(detail);
|
||||
|
||||
assertEquals(2, service.recordError("user-1"));
|
||||
|
||||
assertEquals("2", detail.getCompletionStatus());
|
||||
assertEquals(49.5, detail.getScoreProject());
|
||||
verify(mapper).updateById(detail);
|
||||
}
|
||||
|
||||
@Test
|
||||
void emptyUserDoesNotWriteScore() {
|
||||
assertEquals(0, service.recordError(" "));
|
||||
|
||||
verify(mapper, never()).selectOne(any());
|
||||
verify(mapper, never()).insert(any(StuModuleScoreDetailsEntity.class));
|
||||
verify(mapper, never()).updateById(any(StuModuleScoreDetailsEntity.class));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.yau.digitalrmb.payment.application.service;
|
||||
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsEntity;
|
||||
import com.yau.digitalrmb.institutionidentity.infrastructure.StuModuleScoreDetailsMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class PaymentScoreServiceTest {
|
||||
@Mock private StuModuleScoreDetailsMapper mapper;
|
||||
@InjectMocks private PaymentScoreService service;
|
||||
|
||||
@Test
|
||||
void firstErrorCreatesPaymentScoreDetail() {
|
||||
when(mapper.selectOne(any())).thenReturn(null);
|
||||
|
||||
assertEquals(1, service.recordError("user-1"));
|
||||
|
||||
ArgumentCaptor<StuModuleScoreDetailsEntity> captor =
|
||||
ArgumentCaptor.forClass(StuModuleScoreDetailsEntity.class);
|
||||
verify(mapper).insert(captor.capture());
|
||||
assertEquals("用户支付数字货币", captor.getValue().getMoudule());
|
||||
assertEquals("1", captor.getValue().getCompletionStatus());
|
||||
assertEquals(5, captor.getValue().getSerialNumber());
|
||||
}
|
||||
|
||||
@Test
|
||||
void completedProgressIsPreservedWhenErrorIsRecorded() {
|
||||
StuModuleScoreDetailsEntity detail = new StuModuleScoreDetailsEntity();
|
||||
detail.setCompletionStatus("2");
|
||||
detail.setSchedule(50.0);
|
||||
when(mapper.selectOne(any())).thenReturn(detail);
|
||||
|
||||
service.recordError("user-1");
|
||||
|
||||
assertEquals("3", detail.getCompletionStatus());
|
||||
assertEquals(48.5, detail.getScoreProject());
|
||||
verify(mapper).updateById(detail);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue