Back to Repositories

Testing Data Permission Annotation Interception in RuoYi Vue Pro

This test suite validates the DataPermissionAnnotationInterceptor functionality, focusing on data permission annotation handling at different levels (method, class, and none). It ensures proper interception and cache management for data permission controls.

Test Coverage Overview

The test suite provides comprehensive coverage of DataPermissionAnnotationInterceptor behavior across different annotation scenarios.

  • Tests annotation detection at method level
  • Tests annotation detection at class level
  • Tests behavior with no annotations present
  • Validates cache management and permission enable/disable states

Implementation Analysis

The testing approach utilizes Mockito for dependency isolation and behavior verification.

Key patterns include:
  • Mock injection for MethodInvocation
  • Method invocation simulation using reflection
  • Cache state verification
  • Annotation presence validation at multiple levels

Technical Details

Testing infrastructure includes:

  • JUnit Jupiter for test execution
  • Mockito for mocking and stubbing
  • BaseMockitoUnitTest as the base test class
  • Custom test classes for different annotation scenarios
  • Hutool collection utilities for assertion support

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices through clear organization and thorough validation.

  • Proper test isolation with @BeforeEach setup
  • Comprehensive assertion coverage
  • Clear test method naming conventions
  • Efficient test helper methods
  • Proper mock configuration and verification

yunaiv/ruoyi-vue-pro

yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/test/java/cn/iocoder/yudao/framework/datapermission/core/aop/DataPermissionAnnotationInterceptorTest.java

            
package cn.iocoder.yudao.framework.datapermission.core.aop;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;

import java.lang.reflect.Method;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;

/**
 * {@link DataPermissionAnnotationInterceptor} 的单元测试
 *
 * @author 芋道源码
 */
public class DataPermissionAnnotationInterceptorTest extends BaseMockitoUnitTest {

    @InjectMocks
    private DataPermissionAnnotationInterceptor interceptor;

    @Mock
    private MethodInvocation methodInvocation;

    @BeforeEach
    public void setUp() {
        interceptor.getDataPermissionCache().clear();
    }

    @Test // 无 @DataPermission 注解
    public void testInvoke_none() throws Throwable {
        // 参数
        mockMethodInvocation(TestNone.class);

        // 调用
        Object result = interceptor.invoke(methodInvocation);
        // 断言
        assertEquals("none", result);
        assertEquals(1, interceptor.getDataPermissionCache().size());
        assertTrue(CollUtil.getFirst(interceptor.getDataPermissionCache().values()).enable());
    }

    @Test // 在 Method 上有 @DataPermission 注解
    public void testInvoke_method() throws Throwable {
        // 参数
        mockMethodInvocation(TestMethod.class);

        // 调用
        Object result = interceptor.invoke(methodInvocation);
        // 断言
        assertEquals("method", result);
        assertEquals(1, interceptor.getDataPermissionCache().size());
        assertFalse(CollUtil.getFirst(interceptor.getDataPermissionCache().values()).enable());
    }

    @Test // 在 Class 上有 @DataPermission 注解
    public void testInvoke_class() throws Throwable {
        // 参数
        mockMethodInvocation(TestClass.class);

        // 调用
        Object result = interceptor.invoke(methodInvocation);
        // 断言
        assertEquals("class", result);
        assertEquals(1, interceptor.getDataPermissionCache().size());
        assertFalse(CollUtil.getFirst(interceptor.getDataPermissionCache().values()).enable());
    }

    private void mockMethodInvocation(Class<?> clazz) throws Throwable {
        Object targetObject = clazz.newInstance();
        Method method = targetObject.getClass().getMethod("echo");
        when(methodInvocation.getThis()).thenReturn(targetObject);
        when(methodInvocation.getMethod()).thenReturn(method);
        when(methodInvocation.proceed()).then(invocationOnMock -> method.invoke(targetObject));
    }

    static class TestMethod {

        @DataPermission(enable = false)
        public String echo() {
            return "method";
        }

    }

    @DataPermission(enable = false)
    static class TestClass {

        public String echo() {
            return "class";
        }

    }

    static class TestNone {

        public String echo() {
            return "none";
        }

    }

}