package com.github.ebnew.ki4so.web.action;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import com.github.ebnew.ki4so.core.authentication.Credential;
import com.github.ebnew.ki4so.core.exception.InvalidEncryCredentialException;
import com.github.ebnew.ki4so.core.exception.PasswordInvalidException;
import com.github.ebnew.ki4so.core.exception.UsernameInvalidException;
import com.github.ebnew.ki4so.core.exception.UsernameOrPasswordEmptyException;
import com.github.ebnew.ki4so.core.message.MessageUtils;
import com.github.ebnew.ki4so.core.service.Ki4soService;
import com.github.ebnew.ki4so.core.service.LoginResult;
import com.github.ebnew.ki4so.web.utils.WebConstants;
/**
* LoginAction类测试,包括集成测试和单元测试。
* @author burgess yang
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:spring/springmvc-config.xml", "classpath:spring/spring-beans.xml"})
public class LoginActionTest extends AbstractJUnit4SpringContextTests{
/**
* 被测对象。
*/
@Autowired
private LoginAction loginAction;
@Test
public void unitTestLogin() {
LoginAction action = new LoginAction();
//构造模拟请求和响应对象。
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
CredentialResolver credentialResolver = Mockito.mock(CredentialResolver.class);
action.setCredentialResolver(credentialResolver);
/**
* 测试无任何认证凭据的情况。但是带有service参数,则应该放入到session中保持该参数值。
*/
request.setParameter(WebConstants.SERVICE_PARAM_NAME, "http://test.com/hello.jsp");
ModelAndView mv = action.login(request, response);
Mockito.when(credentialResolver.resolveCredential(request)).thenReturn(null);
Assert.assertNotNull(mv);
//直接返回登录页面。
Assert.assertEquals("login", mv.getViewName());
//无参数输出。
Assert.assertEquals(0, mv.getModel().size());
Assert.assertEquals("http://test.com/hello.jsp", request.getSession().getAttribute(WebConstants.KI4SO_SERVICE_KEY_IN_SESSION));
/**
* 测试返回凭据对象的情况,且存在service参数的情况。
*/
Credential credential = Mockito.mock(Credential.class);
LoginResult loginResult = Mockito.mock(LoginResult.class);
ModelAndView result = Mockito.mock(ModelAndView.class);
Mockito.when(credentialResolver.resolveCredential(request)).thenReturn(credential);
Ki4soService ki4soService = Mockito.mock(Ki4soService.class);
action.setKi4soService(ki4soService);
LoginResultToView loginResultToView = Mockito.mock(LoginResultToView.class);
action.setLoginResultToView(loginResultToView);
Mockito.when(ki4soService.login(Mockito.any(Credential.class))).thenReturn(loginResult);
Mockito.when(loginResultToView.loginResultToView(Mockito.any(ModelAndView.class), Mockito.any(LoginResult.class), Mockito.any(HttpServletRequest.class), Mockito.any(HttpServletResponse.class))).thenReturn(result);
mv = action.login(request, response);
Assert.assertTrue(mv == result);
}
/**
* 登录方法的集成测试
*/
public void integrationTestLogin() {
//构造模拟请求和响应对象。
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
/**
* 测试无任何认证凭据的情况。
*/
ModelAndView mv = loginAction.login(request, response);
Assert.assertNotNull(mv);
//直接返回登录页面。
Assert.assertEquals("login", mv.getViewName());
/**
* 测试有已认证凭据的情况,已认证凭据不合法的情况。
* 则返回登录页面让用户重新输入凭据。
*/
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
//测试模拟一个非法的已加密凭据值。
Cookie cookie = new Cookie(WebConstants.KI4SO_SERVER_ENCRYPTED_CREDENTIAL_COOKIE_KEY, "a invalid KI4SO_SERVER_EC value");
request.setCookies(cookie);
mv = loginAction.login(request, response);
Assert.assertNotNull(mv);
//返回登录页面,带有错误提示信息。
Assert.assertEquals("login", mv.getViewName());
//检查错误代码。
Assert.assertEquals(InvalidEncryCredentialException.CODE, mv.getModel().get("code"));
//检查错误提示信息。
Assert.assertEquals(MessageUtils.getMessage(InvalidEncryCredentialException.MSG_KEY), mv.getModel().get("msg"));
/**
* 测试有已认证凭据的情况,且认证凭据合法的情况。
* 此时返回的地址重新定位到应用的入口地址,带上参数service和WebConstants.KI4SO_CLIENT_ENCRYPTED_CREDENTIAL_COOKIE_KEY
* 其中参数service表示用户想要访问的地址,WebConstants.KI4SO_CLIENT_ENCRYPTED_CREDENTIAL_COOKIE_KEY 表示应用中cookie
*/
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
//传入参数service表示用户要访问的受保护地址URL.
request.setParameter(WebConstants.SERVICE_PARAM_NAME, "http://test.com/user.jsp");
//设置cookie中合法的已认证凭据。
String encCredential = "a valid KI4SO_SERVER_EC value";
cookie = new Cookie(WebConstants.KI4SO_SERVER_ENCRYPTED_CREDENTIAL_COOKIE_KEY, encCredential);
request.setCookies(cookie);
mv = loginAction.login(request, response);
Assert.assertNotNull(mv);
//返回的视图类型是重定向视图。
Assert.assertEquals(RedirectView.class, mv.getView().getClass());
//假设应用的登录入口地址是:http://test.com/loginAction.jsp
Assert.assertEquals("http://test.com/loginAction.jsp?service=http://test.com/user.jsp&"+WebConstants.KI4SO_CLIENT_ENCRYPTED_CREDENTIAL_COOKIE_KEY+"KI4SO CLIENT ENCRYPTED CREDENTIAL COOKIE"
, ((RedirectView)mv.getView()).getUrl());
/**
* 测试有无认证凭据的情况,但是有未认证凭据的情况。
* 即存在用户名和密码参数的情况。但是传入的用户名或者密码是空的情况。
*/
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
//设置用户名和密码都是空。
request.setParameter(UsernamePasswordCredentialResolver.USERNAME_PARAM_NAME, "");
request.setParameter(UsernamePasswordCredentialResolver.PASSWORD_PARAM_NAME, "");
mv = loginAction.login(request, response);
Assert.assertNotNull(mv);
//返回登录页面,带有错误提示信息。
Assert.assertEquals("login", mv.getViewName());
//检查错误代码。
Assert.assertEquals(UsernameOrPasswordEmptyException.CODE, mv.getModel().get("code"));
//检查错误提示信息。
Assert.assertEquals(MessageUtils.getMessage(UsernameOrPasswordEmptyException.MSG_KEY), mv.getModel().get("msg"));
//设置用户名是空,密码不为空的情况。
request.setParameter(UsernamePasswordCredentialResolver.USERNAME_PARAM_NAME, "");
request.setParameter(UsernamePasswordCredentialResolver.PASSWORD_PARAM_NAME, "123456");
mv = loginAction.login(request, response);
Assert.assertNotNull(mv);
//返回登录页面,带有错误提示信息。
Assert.assertEquals("login", mv.getViewName());
//检查错误代码。
Assert.assertEquals(UsernameOrPasswordEmptyException.CODE, mv.getModel().get("code"));
//检查错误提示信息。
Assert.assertEquals(MessageUtils.getMessage(UsernameOrPasswordEmptyException.MSG_KEY), mv.getModel().get("msg"));
//设置用户名不是空,密码是空的情况。
request.setParameter(UsernamePasswordCredentialResolver.USERNAME_PARAM_NAME, "admin");
request.setParameter(UsernamePasswordCredentialResolver.PASSWORD_PARAM_NAME, "");
mv = loginAction.login(request, response);
Assert.assertNotNull(mv);
//返回登录页面,带有错误提示信息。
Assert.assertEquals("login", mv.getViewName());
//检查错误代码。
Assert.assertEquals(UsernameOrPasswordEmptyException.CODE, mv.getModel().get("code"));
//检查错误提示信息。
Assert.assertEquals(MessageUtils.getMessage(UsernameOrPasswordEmptyException.MSG_KEY), mv.getModel().get("msg"));
/**
* 测试有无认证凭据的情况,但是有未认证凭据的情况。
* 即存在用户名和密码参数的情况。但是传入的用户名或者密码不是空,但是用户名不存在的情况。
*/
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
//设置用户名和密码都是空。
request.setParameter(UsernamePasswordCredentialResolver.USERNAME_PARAM_NAME, "admin");
request.setParameter(UsernamePasswordCredentialResolver.PASSWORD_PARAM_NAME, "123456");
mv = loginAction.login(request, response);
Assert.assertNotNull(mv);
//返回登录页面,带有错误提示信息。
Assert.assertEquals("login", mv.getViewName());
//检查错误代码。
Assert.assertEquals(UsernameInvalidException.CODE, mv.getModel().get("code"));
//检查错误提示信息。
Assert.assertEquals(MessageUtils.getMessage(UsernameInvalidException.MSG_KEY), mv.getModel().get("msg"));
/**
* 测试有无认证凭据的情况,但是有未认证凭据的情况。
* 即存在用户名和密码参数的情况。但是传入的用户名或者密码不是空,但是密码不正确的情况。
*/
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
//设置用户名和密码都是空。
request.setParameter(UsernamePasswordCredentialResolver.USERNAME_PARAM_NAME, "admin");
request.setParameter(UsernamePasswordCredentialResolver.PASSWORD_PARAM_NAME, "error");
mv = loginAction.login(request, response);
Assert.assertNotNull(mv);
//返回登录页面,带有错误提示信息。
Assert.assertEquals("login", mv.getViewName());
//检查错误代码。
Assert.assertEquals(PasswordInvalidException.CODE, mv.getModel().get("code"));
//检查错误提示信息。
Assert.assertEquals(MessageUtils.getMessage(PasswordInvalidException.MSG_KEY), mv.getModel().get("msg"));
/**
* 测试有无认证凭据的情况,但是有未认证凭据的情况。
* 即存在用户名和密码参数的情况。但是传入的用户名或者密码不是空,验证通过的情况。
*/
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
//设置用户名和密码都是空。
request.setParameter(UsernamePasswordCredentialResolver.USERNAME_PARAM_NAME, "admin");
request.setParameter(UsernamePasswordCredentialResolver.PASSWORD_PARAM_NAME, "123456");
mv = loginAction.login(request, response);
Assert.assertNotNull(mv);
//返回的视图类型是重定向视图。
Assert.assertEquals(RedirectView.class, mv.getView().getClass());
//假设应用的登录入口地址是:http://test.com/loginAction.jsp
Assert.assertEquals("http://test.com/loginAction.jsp?service=http://test.com/user.jsp&"+WebConstants.KI4SO_CLIENT_ENCRYPTED_CREDENTIAL_COOKIE_KEY+"KI4SO CLIENT ENCRYPTED CREDENTIAL COOKIE"
, ((RedirectView)mv.getView()).getUrl());
//检查写入到response中的cookie值。
Assert.assertNotNull(response.getCookies());
Assert.assertNotNull(response.getCookies()[0]);
Assert.assertEquals(WebConstants.KI4SO_SERVER_ENCRYPTED_CREDENTIAL_COOKIE_KEY, response.getCookies()[0].getName());
Assert.assertNotNull(response.getCookies()[0].getValue());
//检查返回的cookie值是否正确。
}
}