@@ -0,0 +1,238 @@
package cn.iocoder.yudao.framework.business.interceptor ;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum ;
import cn.iocoder.yudao.framework.common.pojo.CompanyDeptInfo ;
import cn.iocoder.yudao.framework.security.core.LoginUser ;
import com.fasterxml.jackson.databind.ObjectMapper ;
import jakarta.servlet.http.HttpServletRequest ;
import jakarta.servlet.http.HttpServletResponse ;
import org.junit.jupiter.api.BeforeEach ;
import org.junit.jupiter.api.Test ;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken ;
import org.springframework.web.method.HandlerMethod ;
import java.io.PrintWriter ;
import java.util.* ;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo ;
import static org.junit.jupiter.api.Assertions.* ;
import static org.mockito.Mockito.* ;
import static org.springframework.security.core.context.SecurityContextHolder.getContext ;
class BusinessHeaderInterceptorTest {
private BusinessHeaderInterceptor interceptor ;
private HttpServletRequest request ;
private HttpServletResponse response ;
private HandlerMethod handlerMethod ;
private PrintWriter writer ;
@BeforeEach
void setUp ( ) throws Exception {
interceptor = new BusinessHeaderInterceptor ( ) ;
request = mock ( HttpServletRequest . class ) ;
response = mock ( HttpServletResponse . class ) ;
handlerMethod = mock ( HandlerMethod . class ) ;
writer = mock ( PrintWriter . class ) ;
when ( response . getWriter ( ) ) . thenReturn ( writer ) ;
}
/**
* 用例:传入的 handler 不是 HandlerMethod, 应该直接返回 true
*/
@Test
void testPreHandle_NotHandlerMethod ( ) throws Exception {
boolean result = interceptor . preHandle ( request , response , new Object ( ) ) ;
assertTrue ( result ) ;
}
/**
* 用例: handlerMethod.getBean() 不是 BusinessControllerMarker, 应该直接返回 true
*/
@Test
void testPreHandle_NotBusinessControllerMarker ( ) throws Exception {
when ( handlerMethod . getBean ( ) ) . thenReturn ( new Object ( ) ) ;
boolean result = interceptor . preHandle ( request , response , handlerMethod ) ;
assertTrue ( result ) ;
}
/**
* 用例: handlerMethod.getBean() 是普通 Controller( 未实现 marker 接口),应直接返回 true
*/
@Test
void testPreHandle_NormalController ( ) throws Exception {
class NormalController { }
when ( handlerMethod . getBean ( ) ) . thenReturn ( new NormalController ( ) ) ;
boolean result = interceptor . preHandle ( request , response , handlerMethod ) ;
assertTrue ( result ) ;
}
/**
* 用例: marker controller, 且 header 无 companyId/deptId, loginUser 有多个公司部门,应该返回 false 并提示 NEED_ADJUST
*/
@Test
void testPreHandle_NoCompanyId_MultiCompanyDept ( ) throws Exception {
class TestBusinessController implements BusinessControllerMarker { }
when ( handlerMethod . getBean ( ) ) . thenReturn ( new TestBusinessController ( ) ) ;
when ( request . getHeader ( " visit-company-id " ) ) . thenReturn ( null ) ;
when ( request . getHeader ( " visit-dept-id " ) ) . thenReturn ( null ) ;
// 构造 loginUser, 包含多个公司部门
LoginUser loginUser = randomPojo ( LoginUser . class , o - > o . setId ( 1L )
. setUserType ( UserTypeEnum . ADMIN . getValue ( ) ) ) ;
Map < String , String > infoMap = new HashMap < > ( ) ;
infoMap . put ( LoginUser . INFO_KEY_COMPANY_DEPT_SET , " [{ \" companyId \" :1, \" deptId \" :2},{ \" companyId \" :2, \" deptId \" :3}] " ) ;
loginUser . setInfo ( infoMap ) ;
// 通过反射或包可见性设置 getLoginUser 返回
setLoginUserForTest ( loginUser ) ;
boolean result = interceptor . preHandle ( request , response , handlerMethod ) ;
assertFalse ( result ) ;
verify ( writer ) . write ( contains ( " 400 " ) ) ;
}
/**
* 用例: header 有 companyId/deptId, loginUser 有多个公司部门,应该正常通过
*/
@Test
void testPreHandle_WithCompanyIdDeptId_MultiCompanyDept ( ) throws Exception {
class TestBusinessController implements BusinessControllerMarker { }
when ( handlerMethod . getBean ( ) ) . thenReturn ( new TestBusinessController ( ) ) ;
when ( request . getHeader ( " visit-company-id " ) ) . thenReturn ( " 1 " ) ;
when ( request . getHeader ( " visit-dept-id " ) ) . thenReturn ( " 2 " ) ;
// 构造 loginUser, 包含多个公司部门
CompanyDeptInfo deptInfo1 = new CompanyDeptInfo ( ) ;
deptInfo1 . setCompanyId ( 1L ) ;
deptInfo1 . setDeptId ( 2L ) ;
CompanyDeptInfo deptInfo2 = new CompanyDeptInfo ( ) ;
deptInfo2 . setCompanyId ( 2L ) ;
deptInfo2 . setDeptId ( 3L ) ;
Set < CompanyDeptInfo > deptSet = new HashSet < > ( ) ;
deptSet . add ( deptInfo1 ) ;
deptSet . add ( deptInfo2 ) ;
LoginUser loginUser = randomPojo ( LoginUser . class , o - > o . setId ( 1L )
. setUserType ( UserTypeEnum . ADMIN . getValue ( ) ) ) ;
String deptSetJson = " [ " +
" { \" companyId \" : " + deptInfo1 . getCompanyId ( ) + " , \" deptId \" : " + deptInfo1 . getDeptId ( ) + " }, " +
" { \" companyId \" : " + deptInfo2 . getCompanyId ( ) + " , \" deptId \" : " + deptInfo2 . getDeptId ( ) + " }] " ;
Map < String , String > infoMap = new HashMap < > ( ) ;
infoMap . put ( LoginUser . INFO_KEY_COMPANY_DEPT_SET , deptSetJson ) ;
loginUser . setInfo ( infoMap ) ;
setLoginUserForTest ( loginUser ) ;
boolean result = interceptor . preHandle ( request , response , handlerMethod ) ;
assertTrue ( result ) ;
}
/**
* 用例: header 无 companyId/deptId, loginUser 只有一个公司部门,应该自动填充 header 并通过
*/
@Test
void testPreHandle_NoHeader_SingleCompanyDept ( ) throws Exception {
class TestBusinessController implements BusinessControllerMarker { }
when ( handlerMethod . getBean ( ) ) . thenReturn ( new TestBusinessController ( ) ) ;
when ( request . getHeader ( " visit-company-id " ) ) . thenReturn ( null ) ;
when ( request . getHeader ( " visit-dept-id " ) ) . thenReturn ( null ) ;
// 构造 loginUser, 只有一个公司且公司下只有一个部门
CompanyDeptInfo deptInfo = new CompanyDeptInfo ( ) ;
deptInfo . setCompanyId ( 100L ) ;
deptInfo . setDeptId ( 200L ) ;
Set < CompanyDeptInfo > deptSet = new HashSet < > ( ) ;
deptSet . add ( deptInfo ) ;
LoginUser loginUser = randomPojo ( LoginUser . class , o - > o . setId ( 1L )
. setUserType ( UserTypeEnum . ADMIN . getValue ( ) ) ) ;
// 只放一个公司部门
String deptSetJson = " [{ \" companyId \" : " + deptInfo . getCompanyId ( ) + " , \" deptId \" : " + deptInfo . getDeptId ( ) + " }] " ;
Map < String , String > infoMap = new HashMap < > ( ) ;
infoMap . put ( LoginUser . INFO_KEY_COMPANY_DEPT_SET , deptSetJson ) ;
loginUser . setInfo ( infoMap ) ;
setLoginUserForTest ( loginUser ) ;
boolean result = interceptor . preHandle ( request , response , handlerMethod ) ;
assertFalse ( result ) ;
// 可选: verify(request).setAttribute("visit-company-id", String.valueOf(deptInfo.getCompanyId()));
// 可选: verify(request).setAttribute("visit-dept-id", String.valueOf(deptInfo.getDeptId()));
}
/**
* 用例: header 无 companyId/deptId, loginUser 有多个公司部门,应该返回 false 并提示 400
*/
@Test
void testPreHandle_NoHeader_MultiCompanyDept ( ) throws Exception {
class TestBusinessController implements BusinessControllerMarker { }
when ( handlerMethod . getBean ( ) ) . thenReturn ( new TestBusinessController ( ) ) ;
when ( request . getHeader ( " visit-company-id " ) ) . thenReturn ( null ) ;
when ( request . getHeader ( " visit-dept-id " ) ) . thenReturn ( null ) ;
// 构造 loginUser, 多个公司部门
CompanyDeptInfo deptInfo1 = new CompanyDeptInfo ( ) ;
deptInfo1 . setCompanyId ( 1L ) ;
deptInfo1 . setDeptId ( 2L ) ;
CompanyDeptInfo deptInfo2 = new CompanyDeptInfo ( ) ;
deptInfo2 . setCompanyId ( 2L ) ;
deptInfo2 . setDeptId ( 3L ) ;
Set < CompanyDeptInfo > deptSet = new HashSet < > ( ) ;
deptSet . add ( deptInfo1 ) ;
deptSet . add ( deptInfo2 ) ;
LoginUser loginUser = randomPojo ( LoginUser . class , o - > o . setId ( 1L )
. setUserType ( UserTypeEnum . ADMIN . getValue ( ) ) ) ;
String deptSetJson = " [ " +
" { \" companyId \" : " + deptInfo1 . getCompanyId ( ) + " , \" deptId \" : " + deptInfo1 . getDeptId ( ) + " }, " +
" { \" companyId \" : " + deptInfo2 . getCompanyId ( ) + " , \" deptId \" : " + deptInfo2 . getDeptId ( ) + " }] " ;
Map < String , String > infoMap = new HashMap < > ( ) ;
infoMap . put ( LoginUser . INFO_KEY_COMPANY_DEPT_SET , deptSetJson ) ;
loginUser . setInfo ( infoMap ) ;
setLoginUserForTest ( loginUser ) ;
boolean result = interceptor . preHandle ( request , response , handlerMethod ) ;
assertFalse ( result ) ;
verify ( writer ) . write ( contains ( " 400 " ) ) ;
}
/**
* 用例: header 有错误的 companyId/deptId, loginUser 不包含该公司部门,应该返回 false 并提示 400
*/
@Test
void testPreHandle_HeaderNotMatchUserCompanyDept ( ) throws Exception {
class TestBusinessController implements BusinessControllerMarker { }
when ( handlerMethod . getBean ( ) ) . thenReturn ( new TestBusinessController ( ) ) ;
when ( request . getHeader ( " visit-company-id " ) ) . thenReturn ( " 999 " ) ;
when ( request . getHeader ( " visit-dept-id " ) ) . thenReturn ( " 888 " ) ;
// 构造 loginUser, 只有其他公司部门
CompanyDeptInfo deptInfo1 = new CompanyDeptInfo ( ) ;
deptInfo1 . setCompanyId ( 1L ) ;
deptInfo1 . setDeptId ( 2L ) ;
CompanyDeptInfo deptInfo2 = new CompanyDeptInfo ( ) ;
deptInfo2 . setCompanyId ( 2L ) ;
deptInfo2 . setDeptId ( 3L ) ;
Set < CompanyDeptInfo > deptSet = new HashSet < > ( ) ;
deptSet . add ( deptInfo1 ) ;
deptSet . add ( deptInfo2 ) ;
LoginUser loginUser = randomPojo ( LoginUser . class , o - > o . setId ( 1L )
. setUserType ( UserTypeEnum . ADMIN . getValue ( ) ) ) ;
String deptSetJson = " [ " +
" { \" companyId \" : " + deptInfo1 . getCompanyId ( ) + " , \" deptId \" : " + deptInfo1 . getDeptId ( ) + " }, " +
" { \" companyId \" : " + deptInfo2 . getCompanyId ( ) + " , \" deptId \" : " + deptInfo2 . getDeptId ( ) + " }] " ;
Map < String , String > infoMap = new HashMap < > ( ) ;
infoMap . put ( LoginUser . INFO_KEY_COMPANY_DEPT_SET , deptSetJson ) ;
loginUser . setInfo ( infoMap ) ;
setLoginUserForTest ( loginUser ) ;
boolean result = interceptor . preHandle ( request , response , handlerMethod ) ;
assertFalse ( result ) ;
verify ( writer ) . write ( contains ( " 400 " ) ) ;
}
// 工具方法:通过 Spring Security 设置当前登录用户,仅测试环境使用
private void setLoginUserForTest ( LoginUser loginUser ) {
// 使用 Spring Security 的 SecurityContextHolder 设置 Authentication
getContext ( )
. setAuthentication ( new UsernamePasswordAuthenticationToken (
loginUser , null , null
) ) ;
}
}