You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
10 KiB
225 lines
10 KiB
package com.mydreamjob.feedback;
|
|
|
|
import com.mydreamjob.application.Application;
|
|
import com.mydreamjob.application.ApplicationRepository;
|
|
import com.mydreamjob.common.exception.BusinessException;
|
|
import com.mydreamjob.common.exception.ErrorCode;
|
|
import com.mydreamjob.company.Company;
|
|
import com.mydreamjob.company.CompanyRepository;
|
|
import com.mydreamjob.feedback.dto.CandidateFeedbackRequest;
|
|
import com.mydreamjob.job.Job;
|
|
import com.mydreamjob.job.JobService;
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.api.extension.ExtendWith;
|
|
import org.mockito.InjectMocks;
|
|
import org.mockito.Mock;
|
|
import org.mockito.junit.jupiter.MockitoExtension;
|
|
|
|
import java.util.Optional;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.Mockito.*;
|
|
|
|
@ExtendWith(MockitoExtension.class)
|
|
class CandidateFeedbackServiceTest {
|
|
|
|
@Mock private CandidateFeedbackRepository feedbackRepository;
|
|
@Mock private ApplicationRepository applicationRepository;
|
|
@Mock private JobService jobService;
|
|
@Mock private CompanyRepository companyRepository;
|
|
@InjectMocks private CandidateFeedbackService feedbackService;
|
|
|
|
private static final Long COMPANY_USER_ID = 10L; // 企业账号 userId
|
|
private static final Long COMPANY_ID = 20L; // 企业 id(job.companyId)
|
|
private static final Long OTHER_COMPANY_USER_ID = 11L; // 其他企业账号 userId
|
|
private static final Long OTHER_COMPANY_ID = 21L; // 其他企业 id
|
|
private static final Long ADMIN_LIKE_USER_ID = 1L; // 无归属企业、且恰等于某企业 id
|
|
private static final Long STUDENT_USER_ID = 100L;
|
|
private static final Long OTHER_STUDENT_ID = 101L;
|
|
private static final Long APPLICATION_ID = 1L;
|
|
private static final Long JOB_ID = 50L;
|
|
private Application app;
|
|
private Job job;
|
|
|
|
@BeforeEach
|
|
void setUp() {
|
|
app = Application.builder().id(APPLICATION_ID).jobId(JOB_ID).studentUserId(STUDENT_USER_ID).build();
|
|
job = Job.builder().id(JOB_ID).companyId(COMPANY_ID).title("Java").build();
|
|
}
|
|
|
|
private void mockCompanyOwnership(Long userId, Long companyId) {
|
|
when(companyRepository.findByOwnerUserId(userId))
|
|
.thenReturn(Optional.of(Company.builder().id(companyId).ownerUserId(userId).build()));
|
|
}
|
|
|
|
private CandidateFeedbackRequest buildReq() {
|
|
CandidateFeedbackRequest req = new CandidateFeedbackRequest();
|
|
req.setRating(4); req.setContent("Good candidate");
|
|
return req;
|
|
}
|
|
|
|
private void stubAppAndJob() {
|
|
when(applicationRepository.findById(APPLICATION_ID)).thenReturn(Optional.of(app));
|
|
when(jobService.getJob(JOB_ID)).thenReturn(job);
|
|
}
|
|
|
|
// ── 创建 ─────────────────────────────────────────────────
|
|
|
|
@Test void createFeedback_companyOwnsJob_shouldSucceed() {
|
|
stubAppAndJob();
|
|
mockCompanyOwnership(COMPANY_USER_ID, COMPANY_ID);
|
|
when(feedbackRepository.existsByApplicationId(APPLICATION_ID)).thenReturn(false);
|
|
when(feedbackRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
|
|
|
|
var r = feedbackService.createFeedback(COMPANY_USER_ID, APPLICATION_ID, buildReq());
|
|
assertEquals(4, r.getRating());
|
|
}
|
|
|
|
@Test void createFeedback_duplicate_shouldReturn409() {
|
|
stubAppAndJob();
|
|
mockCompanyOwnership(COMPANY_USER_ID, COMPANY_ID);
|
|
when(feedbackRepository.existsByApplicationId(APPLICATION_ID)).thenReturn(true);
|
|
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.createFeedback(COMPANY_USER_ID, APPLICATION_ID, buildReq()));
|
|
assertEquals(ErrorCode.DUPLICATE_FEEDBACK.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
|
|
@Test void createFeedback_otherCompany_shouldReturn403() {
|
|
stubAppAndJob();
|
|
mockCompanyOwnership(OTHER_COMPANY_USER_ID, OTHER_COMPANY_ID);
|
|
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.createFeedback(OTHER_COMPANY_USER_ID, APPLICATION_ID, buildReq()));
|
|
assertEquals(ErrorCode.FORBIDDEN.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
|
|
@Test void createFeedback_adminUserIdEqualsCompanyId_shouldReturn403() {
|
|
// userId 恰等于 job.companyId,但该用户无归属企业 -> 必须 403(安全回归)
|
|
Job adminJob = Job.builder().id(JOB_ID).companyId(ADMIN_LIKE_USER_ID).title("Java").build();
|
|
when(applicationRepository.findById(APPLICATION_ID)).thenReturn(Optional.of(app));
|
|
when(jobService.getJob(JOB_ID)).thenReturn(adminJob);
|
|
// 不 stub companyRepository:默认空 -> 无归属企业
|
|
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.createFeedback(ADMIN_LIKE_USER_ID, APPLICATION_ID, buildReq()));
|
|
assertEquals(ErrorCode.FORBIDDEN.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
|
|
@Test void createFeedback_byStudent_shouldReturn403() {
|
|
stubAppAndJob();
|
|
// 学生无归属企业
|
|
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.createFeedback(STUDENT_USER_ID, APPLICATION_ID, buildReq()));
|
|
assertEquals(ErrorCode.FORBIDDEN.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
|
|
@Test void createFeedback_appNotFound_shouldReturn404() {
|
|
when(applicationRepository.findById(999L)).thenReturn(Optional.empty());
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.createFeedback(COMPANY_USER_ID, 999L, buildReq()));
|
|
assertEquals(ErrorCode.APPLICATION_NOT_FOUND.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
|
|
// ── 查询 ─────────────────────────────────────────────────
|
|
|
|
@Test void getFeedback_asCompany_shouldSucceed() {
|
|
stubAppAndJob();
|
|
mockCompanyOwnership(COMPANY_USER_ID, COMPANY_ID);
|
|
CandidateFeedback fb = CandidateFeedback.builder().applicationId(APPLICATION_ID).rating(4).content("Good").build();
|
|
when(feedbackRepository.findByApplicationId(APPLICATION_ID)).thenReturn(Optional.of(fb));
|
|
|
|
var r = feedbackService.getFeedback(COMPANY_USER_ID, APPLICATION_ID);
|
|
assertEquals(4, r.getRating());
|
|
}
|
|
|
|
@Test void getFeedback_asStudent_shouldSucceed() {
|
|
stubAppAndJob();
|
|
CandidateFeedback fb = CandidateFeedback.builder().applicationId(APPLICATION_ID).rating(4).content("Good").build();
|
|
when(feedbackRepository.findByApplicationId(APPLICATION_ID)).thenReturn(Optional.of(fb));
|
|
|
|
var r = feedbackService.getFeedback(STUDENT_USER_ID, APPLICATION_ID);
|
|
assertEquals(4, r.getRating());
|
|
}
|
|
|
|
@Test void getFeedback_adminUserIdEqualsCompanyId_shouldReturn403() {
|
|
Job adminJob = Job.builder().id(JOB_ID).companyId(ADMIN_LIKE_USER_ID).title("Java").build();
|
|
when(applicationRepository.findById(APPLICATION_ID)).thenReturn(Optional.of(app));
|
|
when(jobService.getJob(JOB_ID)).thenReturn(adminJob);
|
|
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.getFeedback(ADMIN_LIKE_USER_ID, APPLICATION_ID));
|
|
assertEquals(ErrorCode.FORBIDDEN.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
|
|
@Test void getFeedback_otherStudent_shouldReturn403() {
|
|
stubAppAndJob();
|
|
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.getFeedback(OTHER_STUDENT_ID, APPLICATION_ID));
|
|
assertEquals(ErrorCode.FORBIDDEN.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
|
|
// ── 修改 ─────────────────────────────────────────────────
|
|
|
|
@Test void updateFeedback_shouldSucceed() {
|
|
stubAppAndJob();
|
|
mockCompanyOwnership(COMPANY_USER_ID, COMPANY_ID);
|
|
CandidateFeedback fb = CandidateFeedback.builder().applicationId(APPLICATION_ID).rating(4).content("Good").build();
|
|
when(feedbackRepository.findByApplicationId(APPLICATION_ID)).thenReturn(Optional.of(fb));
|
|
when(feedbackRepository.save(any())).thenAnswer(inv -> inv.getArgument(0));
|
|
|
|
CandidateFeedbackRequest req = buildReq(); req.setRating(5);
|
|
var r = feedbackService.updateFeedback(COMPANY_USER_ID, APPLICATION_ID, req);
|
|
assertEquals(5, r.getRating());
|
|
}
|
|
|
|
@Test void updateFeedback_otherCompany_shouldReturn403() {
|
|
stubAppAndJob();
|
|
mockCompanyOwnership(OTHER_COMPANY_USER_ID, OTHER_COMPANY_ID);
|
|
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.updateFeedback(OTHER_COMPANY_USER_ID, APPLICATION_ID, buildReq()));
|
|
assertEquals(ErrorCode.FORBIDDEN.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
|
|
@Test void updateFeedback_byStudent_shouldReturn403() {
|
|
stubAppAndJob();
|
|
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.updateFeedback(STUDENT_USER_ID, APPLICATION_ID, buildReq()));
|
|
assertEquals(ErrorCode.FORBIDDEN.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
|
|
// ── 删除 ─────────────────────────────────────────────────
|
|
|
|
@Test void deleteFeedback_shouldSucceed() {
|
|
stubAppAndJob();
|
|
mockCompanyOwnership(COMPANY_USER_ID, COMPANY_ID);
|
|
CandidateFeedback fb = CandidateFeedback.builder().applicationId(APPLICATION_ID).build();
|
|
when(feedbackRepository.findByApplicationId(APPLICATION_ID)).thenReturn(Optional.of(fb));
|
|
|
|
assertDoesNotThrow(() -> feedbackService.deleteFeedback(COMPANY_USER_ID, APPLICATION_ID));
|
|
verify(feedbackRepository).delete(fb);
|
|
}
|
|
|
|
@Test void deleteFeedback_otherCompany_shouldReturn403() {
|
|
stubAppAndJob();
|
|
mockCompanyOwnership(OTHER_COMPANY_USER_ID, OTHER_COMPANY_ID);
|
|
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.deleteFeedback(OTHER_COMPANY_USER_ID, APPLICATION_ID));
|
|
assertEquals(ErrorCode.FORBIDDEN.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
|
|
@Test void deleteFeedback_byStudent_shouldReturn403() {
|
|
stubAppAndJob();
|
|
|
|
BusinessException ex = assertThrows(BusinessException.class,
|
|
() -> feedbackService.deleteFeedback(STUDENT_USER_ID, APPLICATION_ID));
|
|
assertEquals(ErrorCode.FORBIDDEN.getCode(), ex.getErrorCodeInt());
|
|
}
|
|
}
|
|
|