使用easymock / powermock模拟超级方法调用 [英] Mocking super method call using easymock/powermock

查看:188
本文介绍了使用easymock / powermock模拟超级方法调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将easymock与Spring项目集成在一起,并执行了大多数单元测试。但是遇到了无法模拟超级方法的问题。当我运行测试类时,它说不支持该方法。

I integrated easymock with my Spring project and performed most of the unit tests. But got an issue with not able to mock the super method. When I run my test class it says method not supported.

任何想法都出了什么问题,因为我在过去的几天里尽力而为,没有任何线索如何模拟超级方法。

Any idea what's going wrong as I tried my best for last couple of days and not able to get any clue on how to mock the super method.

org.springframework.security.authentication.AuthenticationServiceException: Authentication method not supported: 
    at org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:71)
    at com.dashboard.core.CustomAuthenticationFilter.attemptAuthentication(CustomAuthenticationFilter.java:20)
    at com.dashboard.core.CustomAuthenticationFilterTest.testAttemptAuthentication(CustomAuthenticationFilterTest.java:64)

要测试的类:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.dashboard.domain.ApplicationConstant;

public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
        String username = request.getParameter("j_username");
        String password = request.getParameter("j_password");
        if(isValidUsername(username) && isValidPassword(password) ){
            return super.attemptAuthentication(request, response);
        }
        throw new BadCredentialsException(ApplicationConstant.CREDENTIALS_NOT_FORMAT.getValue());
    }

    private static boolean isValidUsername(String username){
        return !StringUtils.isEmpty(username) && username.matches(ApplicationConstant.USERNAME_PATTERN.getValue());
    }

    private static boolean isValidPassword(String password){
        return !StringUtils.isEmpty(password) && password.matches(ApplicationConstant.PWD_PATTERN.getValue());
    }
}

我的测试班:

import java.util.ArrayList;
import java.util.List;

import org.easymock.EasyMock;
import org.easymock.EasyMockRunner;
import org.easymock.EasyMockSupport;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@RunWith(EasyMockRunner.class)
public class CustomAuthenticationFilterTest extends EasyMockSupport{

    @TestSubject
    CustomAuthenticationFilter customAuthenticationFilter  = new CustomAuthenticationFilter();

    @Mock
    UsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter;

    @Test
    public void testAttemptAuthentication() throws Exception{   
        MockHttpServletRequest request = new MockHttpServletRequest();
        request.setParameter("j_username", "Sundar1234");
        request.setParameter("j_password", "Sundar1234$$");
        MockHttpServletResponse response = new MockHttpServletResponse();
        SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
        List<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
        updatedAuthorities.add(authority);
        User user = new User("Sundar1234", "Sundar1234$$", updatedAuthorities);
        Authentication auth = new UsernamePasswordAuthenticationToken(user,null);
        EasyMock.expect(usernamePasswordAuthenticationFilter.attemptAuthentication(request, response)).andReturn(auth);
        EasyMock.replay(usernamePasswordAuthenticationFilter);
        Assert.assertNotNull(customAuthenticationFilter.attemptAuthentication(request, response));
        EasyMock.verify(usernamePasswordAuthenticationFilter);
    }
}


推荐答案

UsernamePasswordAuthenticationFilter 是基类,而不是注入的依赖项。通常,您可以使用部分模拟解决此问题。但是,由于 CustomAuthenticationFilter 调用了无法嘲笑的 super.attemptAuthentication ,您不能这样做。

UsernamePasswordAuthenticationFilter is a base class, not an injected dependency. Normally, you can workaround that by using a partial mock. But you can't since CustomAuthenticationFilter is calling super.attemptAuthentication which can't be mocked.

您的解决方案是:


  1. 测试 CustomAuthenticationFilter 及其全部超类

  2. 改用委托模式

  1. Test CustomAuthenticationFilter and its superclass altogether
  2. Use a delegation pattern instead

但是由于当前的春季对于此类过滤器的设计,委托似乎笨拙。因此,总的来说,测试是您最好的选择。

But because of the current Spring design for such filter, delegating seems clunky. So testing altogether is I think your best bet.

这篇关于使用easymock / powermock模拟超级方法调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆