轻松聘AI开发
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.
 
 
 

145 lines
6.9 KiB

package com.mydreamjob.application;
import com.mydreamjob.auth.User;
import com.mydreamjob.company.Company;
import com.mydreamjob.job.Job;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import org.hibernate.SessionFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.transaction.annotation.Transactional;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@SpringBootTest(properties = "spring.jpa.properties.hibernate.generate_statistics=true")
@AutoConfigureMockMvc
@ActiveProfiles("integration-test")
@Transactional
class ApplicationSummaryIntegrationTest {
@Autowired EntityManager em;
@Autowired EntityManagerFactory emf;
@Autowired ApplicationService service;
@Autowired MockMvc mvc;
@Autowired com.mydreamjob.auth.AuthSessionService sessions;
@Autowired java.time.Clock clock;
@MockBean RedisTemplate<String, Object> redis;
long studentId;
long otherStudentId;
@BeforeEach
void fixture() {
User student = user("summary-student", User.Role.STUDENT);
User other = user("summary-other", User.Role.STUDENT);
User owner = user("summary-company", User.Role.COMPANY);
studentId = student.getId();
otherStudentId = other.getId();
Company company = Company.builder().ownerUserId(owner.getId()).name("摘要测试企业").verified(true).build();
em.persist(company);
for (int i = 0; i < 55; i++) {
Job job = Job.builder().companyId(company.getId()).title("岗位" + i).description("测试")
.city("上海").employmentType("FULL_TIME").status(i == 0 ? "CLOSED" : "PUBLISHED")
.salaryMin(i == 0 ? null : 10000).salaryMax(i == 0 ? null : 20000).build();
em.persist(job);
em.persist(Application.builder().jobId(job.getId()).studentUserId(studentId)
.status(i % 2 == 0 ? "SUBMITTED" : "WITHDRAWN").build());
if (i == 0) em.persist(Application.builder().jobId(job.getId()).studentUserId(otherStudentId)
.status("SUBMITTED").build());
}
em.flush();
em.clear();
}
private User user(String name, User.Role role) {
User user = User.builder().phone("139" + Math.abs(System.nanoTime() % 1_000_000_000L))
.nickname(name).role(role).roles(Set.of(role)).active(true).verified(true).build();
em.persist(user);
return user;
}
@Test
void fixedQueryBudgetAndAllSummaryFieldsForOneTwentyAndFiftyRows() {
var stats = emf.unwrap(SessionFactory.class).getStatistics();
for (int size : new int[]{1, 20, 50}) {
em.clear();
stats.clear();
var page = service.listStudentApplicationViews(studentId, null, 0, size);
long statements = stats.getPrepareStatementCount();
assertEquals(3, statements, "当前页、总数、批量岗位摘要共三条 SQL,size=" + size);
assertEquals(55, page.getTotalElements());
assertEquals(size, page.getNumberOfElements());
for (var item : page) {
assertEquals(studentId, item.get("studentUserId"));
assertEquals("摘要测试企业", item.get("companyName"));
assertEquals("上海", item.get("city"));
assertEquals("FULL_TIME", item.get("employmentType"));
assertTrue(item.get("jobTitle").toString().startsWith("岗位"));
assertNotNull(item.get("companyId"));
assertTrue(item.containsKey("salaryMin"));
assertTrue(item.containsKey("salaryMax"));
assertNotNull(item.get("jobStatus"));
assertNotNull(item.get("status"));
assertNotNull(item.get("createdAt"));
}
}
}
@Test
void statusFilterPaginationAndIsolationArePreserved() {
var page = service.listStudentApplicationViews(studentId, "SUBMITTED", 1, 20);
assertEquals(28, page.getTotalElements());
assertEquals(2, page.getTotalPages());
assertEquals(1, page.getNumber());
assertEquals(8, page.getNumberOfElements());
page.forEach(item -> assertEquals("SUBMITTED", item.get("status")));
var other = service.listStudentApplicationViews(otherStudentId, null, 0, 20);
assertEquals(1, other.getTotalElements());
var closed = other.getContent().get(0);
assertEquals("CLOSED", closed.get("jobStatus"));
assertEquals("SUBMITTED", closed.get("status"));
assertNull(closed.get("salaryMin"));
assertNull(closed.get("salaryMax"));
}
@Test
void emptyPageSkipsSummarySql() {
var stats = emf.unwrap(SessionFactory.class).getStatistics();
stats.clear();
var page = service.listStudentApplicationViews(studentId, "HIRED", 0, 20);
assertTrue(page.isEmpty());
assertEquals(0, page.getTotalElements());
assertEquals(1, stats.getPrepareStatementCount());
}
@Test
void rejectsInvalidPagination() {
assertThrows(com.mydreamjob.common.exception.BusinessException.class,
() -> service.listStudentApplicationViews(studentId, null, -1, 20));
assertThrows(com.mydreamjob.common.exception.BusinessException.class,
() -> service.listStudentApplicationViews(studentId, null, 0, 101));
}
@Test
void httpListReturnsSummaryAndUnchangedPageEnvelope() throws Exception {
String bearer = "Bearer " + sessions.createSession(em.find(User.class, studentId), clock.instant(),
com.mydreamjob.audit.AuditContext.builder().requestId("application-summary-test").build()).accessToken();
mvc.perform(get("/applications/me").header("Authorization", bearer).param("size", "20"))
.andExpect(status().isOk()).andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.data.total").value(55))
.andExpect(jsonPath("$.data.totalPages").value(3))
.andExpect(jsonPath("$.data.items.length()").value(20))
.andExpect(jsonPath("$.data.items[0].companyName").value("摘要测试企业"))
.andExpect(jsonPath("$.data.items[0].jobTitle").isString());
mvc.perform(get("/applications/me")).andExpect(status().isUnauthorized());
}
}