forked from baskbuddy/zhangshun
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
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());
|
|
}
|
|
}
|
|
|