我正在尝试为以下课程创建单元测试:

@Secured
@Provider
@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {

    @Context
    private ResourceInfo resourceInfo;

    @Context
    private SecurityContext securityContext;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        // Get the resource class which matches with the requested URL
        // Extract the permissions declared by it
        Class<?> resourceClass = resourceInfo.getResourceClass();
        List<Permission> classPermissions = extractPermissions(resourceClass);

        // Get the resource method which matches with the requested URL
        // Extract the permissions declared by it
        Method resourceMethod = resourceInfo.getResourceMethod();
        List<Permission> methodPermissions = extractPermissions(resourceMethod);

        try {
            String email = securityContext.getUserPrincipal().getName();

            // Check if the user is allowed to execute the method
            // The method annotations override the class annotations
            if (methodPermissions.isEmpty()) {
                checkPermissions(email, classPermissions);
            } else {
                checkPermissions(email, methodPermissions);
            }

        } catch (NotAuthorizedException e) {
            requestContext.abortWith(
                Response.status(Response.Status.FORBIDDEN).build());
        }
    }

    // Extract the permissions from the annotated element
    private List<Permission> extractPermissions(AnnotatedElement annotatedElement) {
        // get permissions
        return permissions;
    }

    protected void checkPermissions(String email, List<Permission> allowedPermissions) throws NotAuthorizedException {
        Permissions permissions = DBUserUtils.getUserPermissions(email);
        for (Permission permission : allowedPermissions){
            if (!permissions.hasPermission(permission))
                throw new NotAuthorizedException("Authorization header must be provided");;
        }
    }
}


在我当前的测试课程中:

@RunWith(MockitoJUnitRunner.class)
public class AuthorizationFilterTest {

    @Mock
    private ResourceInfo resourceInfo = mock(ResourceInfo.class);

    @Mock
    private SecurityContext securityContext = mock(SecurityContext.class);

    @Mock
    private static DBUserUtils dbUserUtils = mock(DBUserUtils.class);

    @InjectMocks
    private AuthorizationFilter authorizationFilter = spy(AuthorizationFilter.class);

    private ContainerRequestContext requestContext = mock(ContainerRequestContext.class);

    @Before
    public void initMocks() {
        MockitoAnnotations.initMocks(this);

        doReturn(Endpoints.class).when(resourceInfo).getResourceClass();

        when(securityContext.getUserPrincipal()).thenReturn(new UserPrincipal() {
            @Override
            public String getName() {
                return "email";
            }
        });
    }


    @Test
    public void authorizationFilterAuthorizedTest() throws NotAuthorizedException, IOException{
        doReturn(getMethodByName(Endpoints.class, "createUser")).when(resourceInfo).getResourceMethod();
        authorizationFilter.filter(requestContext);
        verify(requestContext, times(0)).abortWith(any());
    }

    private Method getMethodByName(Class<?> classToUse, String methodName){
        Method[] methods = classToUse.getMethods();
        for (Method method : methods){
            if (method.getName().equals(methodName))
                return method;
        }
        return null;
    }
}


我能够模拟类的私有字段,但似乎找不到模拟静态方法DBUserUtils.getUserPermissions(email)的方法。这可能还是我只是在浪费时间?

我正在使用Mockito 1.10.19和JUnit 4进行测试。

我是模拟单元测试对象的新手,所以如果我在某个地方犯了很大的错误,请告诉我!

谢谢。

最佳答案

要在您的示例中模拟DBUserUtils.getUserPermissions(email),您可以a)使用一些其他框架(例如PowerMock,如问题注释中所述),或b)将对DBUserUtils.getUserPermissions(email)的调用提取到单独的方法:

Permissions getUserPermissions(String email) {
    return DBUserUtils.getUserPermissions(email);
}


然后可以在测试中进行模拟:

doReturn(...).when(authorizationFilter).getUserPermissions(any());

10-01 23:43