|
@@ -29,6 +29,9 @@ public class HealthReportServiceTest {
|
|
|
@Mock
|
|
@Mock
|
|
|
private com.etotem.cfc.mapper.HealthReportPermissionMapper healthReportPermissionMapper;
|
|
private com.etotem.cfc.mapper.HealthReportPermissionMapper healthReportPermissionMapper;
|
|
|
|
|
|
|
|
|
|
+ @Mock
|
|
|
|
|
+ private com.etotem.cfc.mapper.FamilyMemberMapper familyMemberMapper;
|
|
|
|
|
+
|
|
|
@Mock
|
|
@Mock
|
|
|
private DimensionScoreService dimensionScoreService;
|
|
private DimensionScoreService dimensionScoreService;
|
|
|
|
|
|
|
@@ -43,9 +46,11 @@ public class HealthReportServiceTest {
|
|
|
@BeforeEach
|
|
@BeforeEach
|
|
|
public void setUp() {
|
|
public void setUp() {
|
|
|
MockitoAnnotations.openMocks(this);
|
|
MockitoAnnotations.openMocks(this);
|
|
|
|
|
+ initMybatisPlusMetadata();
|
|
|
service = new HealthReportService();
|
|
service = new HealthReportService();
|
|
|
setField(service, "healthReportMapper", healthReportMapper);
|
|
setField(service, "healthReportMapper", healthReportMapper);
|
|
|
setField(service, "healthReportPermissionMapper", healthReportPermissionMapper);
|
|
setField(service, "healthReportPermissionMapper", healthReportPermissionMapper);
|
|
|
|
|
+ setField(service, "familyMemberMapper", familyMemberMapper);
|
|
|
setField(service, "dimensionScoreService", dimensionScoreService);
|
|
setField(service, "dimensionScoreService", dimensionScoreService);
|
|
|
setField(service, "foodRecommendService", foodRecommendService);
|
|
setField(service, "foodRecommendService", foodRecommendService);
|
|
|
setField(service, "jdbcTemplate", jdbcTemplate);
|
|
setField(service, "jdbcTemplate", jdbcTemplate);
|
|
@@ -61,6 +66,20 @@ public class HealthReportServiceTest {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 纯单测没有 Spring/MyBatis 初始化,LambdaQueryWrapper.getSqlSegment() 解析
|
|
|
|
|
+ * @TableField 需要实体元数据缓存,否则抛 can not find lambda cache。
|
|
|
|
|
+ * 这里显式注册,使 SQL 片段可被断言。
|
|
|
|
|
+ */
|
|
|
|
|
+ private void initMybatisPlusMetadata() {
|
|
|
|
|
+ org.apache.ibatis.builder.MapperBuilderAssistant assistant =
|
|
|
|
|
+ new org.apache.ibatis.builder.MapperBuilderAssistant(
|
|
|
|
|
+ new com.baomidou.mybatisplus.core.MybatisConfiguration(), "");
|
|
|
|
|
+ assistant.setCurrentNamespace("health-report-service-test");
|
|
|
|
|
+ com.baomidou.mybatisplus.core.metadata.TableInfoHelper.initTableInfo(
|
|
|
|
|
+ assistant, HealthReport.class);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private HealthReport report(Long id, Long familyId, Long subjectId, String status) {
|
|
private HealthReport report(Long id, Long familyId, Long subjectId, String status) {
|
|
|
HealthReport r = new HealthReport();
|
|
HealthReport r = new HealthReport();
|
|
|
r.setId(id);
|
|
r.setId(id);
|
|
@@ -91,7 +110,8 @@ public class HealthReportServiceTest {
|
|
|
|
|
|
|
|
verify(jdbcTemplate).update(eq("UPDATE health_reports SET subject_id = ? WHERE id = ?"),
|
|
verify(jdbcTemplate).update(eq("UPDATE health_reports SET subject_id = ? WHERE id = ?"),
|
|
|
eq(null), eq(1L));
|
|
eq(null), eq(1L));
|
|
|
- verify(dimensionScoreService).refreshFromGutReport(eq(20L), eq(1L));
|
|
|
|
|
|
|
+ verify(dimensionScoreService).rebuildFromMemberReports(eq(20L));
|
|
|
|
|
+ verify(dimensionScoreService, never()).refreshFromGutReport(eq(20L), anyLong());
|
|
|
verify(foodRecommendService).recalculateForUser(eq(20L));
|
|
verify(foodRecommendService).recalculateForUser(eq(20L));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -115,7 +135,7 @@ public class HealthReportServiceTest {
|
|
|
|
|
|
|
|
verify(jdbcTemplate).update(eq("UPDATE health_reports SET subject_id = ? WHERE id = ?"),
|
|
verify(jdbcTemplate).update(eq("UPDATE health_reports SET subject_id = ? WHERE id = ?"),
|
|
|
eq(30L), eq(1L));
|
|
eq(30L), eq(1L));
|
|
|
- verify(dimensionScoreService).refreshFromGutReport(eq(20L), eq(1L));
|
|
|
|
|
|
|
+ verify(dimensionScoreService).rebuildFromMemberReports(eq(20L));
|
|
|
verify(dimensionScoreService).refreshFromGutReport(eq(30L), eq(1L));
|
|
verify(dimensionScoreService).refreshFromGutReport(eq(30L), eq(1L));
|
|
|
verify(foodRecommendService).recalculateForUser(eq(20L));
|
|
verify(foodRecommendService).recalculateForUser(eq(20L));
|
|
|
verify(foodRecommendService).recalculateForUser(eq(30L));
|
|
verify(foodRecommendService).recalculateForUser(eq(30L));
|
|
@@ -140,6 +160,36 @@ public class HealthReportServiceTest {
|
|
|
verify(jdbcTemplate, never()).update(anyString(), any(), anyLong());
|
|
verify(jdbcTemplate, never()).update(anyString(), any(), anyLong());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // ── getMemberReports:家庭隔离 ─────────────────────────────────────
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 回归:getMemberReports 曾只按 subject_id/user_id 匹配,完全不带 family_id 条件,
|
|
|
|
|
+ * 导致家庭72的成员列表混入家庭67/70的报告(实测 7 条中 5 条越界)。
|
|
|
|
|
+ * 小程序照单显示"取消归属",点击后在 reassignReport 权限校验处抛
|
|
|
|
|
+ * "报告不属于该家庭"。列表侧必须与权限侧保持同一条家庭边界。
|
|
|
|
|
+ */
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void getMemberReports_constrainsToMemberFamily() {
|
|
|
|
|
+ com.etotem.cfc.entity.FamilyMember fm = new com.etotem.cfc.entity.FamilyMember();
|
|
|
|
|
+ fm.setId(21L);
|
|
|
|
|
+ fm.setFamilyId(72L);
|
|
|
|
|
+ fm.setUserId(12L);
|
|
|
|
|
+ when(familyMemberMapper.selectById(21L)).thenReturn(fm);
|
|
|
|
|
+ when(familyMemberMapper.selectList(any())).thenReturn(Collections.emptyList());
|
|
|
|
|
+ when(healthReportMapper.selectList(any())).thenReturn(Collections.emptyList());
|
|
|
|
|
+
|
|
|
|
|
+ service.getMemberReports(21L);
|
|
|
|
|
+
|
|
|
|
|
+ org.mockito.ArgumentCaptor<com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper> captor =
|
|
|
|
|
+ org.mockito.ArgumentCaptor.forClass(
|
|
|
|
|
+ com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper.class);
|
|
|
|
|
+ verify(healthReportMapper).selectList(captor.capture());
|
|
|
|
|
+ String sql = captor.getValue().getSqlSegment();
|
|
|
|
|
+ assertTrue(sql.contains("family_id"), "getMemberReports 必须限定 family_id,实际SQL: " + sql);
|
|
|
|
|
+ assertTrue(captor.getValue().getParamNameValuePairs().containsValue(72L),
|
|
|
|
|
+ "查询条件必须携带成员所在家庭ID 72,实际: " + captor.getValue().getParamNameValuePairs());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// ── getUnlinkedReports ──────────────────────────────────────────────
|
|
// ── getUnlinkedReports ──────────────────────────────────────────────
|
|
|
|
|
|
|
|
@Test
|
|
@Test
|