org.jtalks.common.web.controller.UserControllerTest.java Source code

Java tutorial

Introduction

Here is the source code for org.jtalks.common.web.controller.UserControllerTest.java

Source

/**
 * Copyright (C) 2011  JTalks.org Team
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package org.jtalks.common.web.controller;

import org.jtalks.common.model.entity.User;
import org.jtalks.common.service.SecurityService;
import org.jtalks.common.service.UserService;
import org.jtalks.common.service.exceptions.DuplicateEmailException;
import org.jtalks.common.service.exceptions.DuplicateUserException;
import org.jtalks.common.service.exceptions.NotFoundException;
import org.jtalks.common.service.exceptions.WrongPasswordException;
import org.jtalks.common.web.dto.user.EditUserProfileDto;
import org.jtalks.common.web.dto.user.RegisterUserDto;
import org.jtalks.common.web.validation.ImageFormats;
import org.mockito.Matchers;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Array;

import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.ModelAndViewAssert.assertAndReturnModelAttributeOfType;
import static org.springframework.test.web.ModelAndViewAssert.assertModelAttributeAvailable;
import static org.springframework.test.web.ModelAndViewAssert.assertViewName;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;

/**
 * @author Kirill Afonin
 * @author Osadchuck Eugeny
 * @author Dmitry Sokolov
 */
public class UserControllerTest {
    private UserService userService;
    private SecurityService securityService;
    private UserController controller;

    private final String USER_NAME = "username";
    private final String ENCODED_USER_NAME = "encodeUsername";
    private final String FIRST_NAME = "first name";
    private final String LAST_NAME = "last name";
    private final String EMAIL = "mail@mail.com";
    private final String PASSWORD = "password";
    private final String NEW_PASSWORD = "newPassword";
    private final byte[] DEFAULT_AVATAR = new byte[] { 1, 2, 3, 4, 5 };
    private MultipartFile avatar;

    @BeforeClass
    public void mockAvatar() throws IOException {
        avatar = new MockMultipartFile("test_avatar.jpg", "test_avatar.jpg", "image/jpeg", new byte[10]);
    }

    @BeforeMethod
    public void setUp() throws IOException {
        userService = mock(UserService.class);
        securityService = mock(SecurityService.class);
        controller = new UserController(userService, securityService);
    }

    @Test
    public void testRegistrationPage() throws Exception {
        ModelAndView mav = controller.registrationPage();

        assertViewName(mav, "registration");
        RegisterUserDto dto = assertAndReturnModelAttributeOfType(mav, "newUser", RegisterUserDto.class);
        assertNullFields(dto);
    }

    private void assertNullFields(RegisterUserDto dto) {
        assertNull(dto.getEmail());
        assertNull(dto.getUsername());
        assertNull(dto.getPassword());
        assertNull(dto.getPasswordConfirm());
        assertNull(dto.getLastName());
        assertNull(dto.getFirstName());
    }

    @Test
    public void testRegisterUser() throws Exception {
        RegisterUserDto dto = getRegisterUserDto();
        BindingResult bindingResult = new BeanPropertyBindingResult(dto, "newUser");

        ModelAndView mav = controller.registerUser(dto, bindingResult);

        assertViewName(mav, "redirect:/");
        verify(userService).registerUser(Matchers.any(User.class));
    }

    @Test
    public void testRegisterDuplicateUser() throws Exception {
        RegisterUserDto dto = getRegisterUserDto();
        BindingResult bindingResult = new BeanPropertyBindingResult(dto, "newUser");
        doThrow(new DuplicateUserException("User username already exists!")).when(userService)
                .registerUser(Matchers.any(User.class));

        ModelAndView mav = controller.registerUser(dto, bindingResult);

        assertViewName(mav, "registration");
        assertEquals(bindingResult.getErrorCount(), 1, "Result without errors");
        verify(userService).registerUser(Matchers.any(User.class));
    }

    @Test
    public void testRegisterUserWithDuplicateEmail() throws Exception {
        RegisterUserDto dto = getRegisterUserDto();
        BindingResult bindingResult = new BeanPropertyBindingResult(dto, "newUser");
        doThrow(new DuplicateEmailException("E-mail mail@mail.com already exists!")).when(userService)
                .registerUser(Matchers.any(User.class));

        ModelAndView mav = controller.registerUser(dto, bindingResult);

        assertViewName(mav, "registration");
        assertEquals(bindingResult.getErrorCount(), 1, "Result without errors");
        verify(userService).registerUser(Matchers.any(User.class));
    }

    @Test
    public void testRegisterValidationFail() {
        RegisterUserDto dto = getRegisterUserDto();
        BindingResult bindingResult = mock(BindingResult.class);
        when(bindingResult.hasErrors()).thenReturn(true);

        ModelAndView mav = controller.registerUser(dto, bindingResult);

        assertViewName(mav, "registration");
    }

    @Test
    public void testShow() throws Exception {
        //set expectations
        when(userService.getByEncodedUsername(ENCODED_USER_NAME))
                .thenReturn(new User("username", "email", "password"));

        //invoke the object under test
        ModelAndView mav = controller.show(ENCODED_USER_NAME);

        //check expectations
        verify(userService).getByEncodedUsername(ENCODED_USER_NAME);

        //check result
        assertViewName(mav, "userDetails");
        assertModelAttributeAvailable(mav, "user");
    }

    @Test
    public void testEditProfilePage() throws NotFoundException, IOException {
        User user = getUser();
        //set expectations
        when(securityService.getCurrentUser()).thenReturn(user);

        //invoke the object under test
        ModelAndView mav = controller.editProfilePage();

        //check expectations
        verify(securityService).getCurrentUser();

        //check result
        assertViewName(mav, "editProfile");
        EditUserProfileDto dto = assertAndReturnModelAttributeOfType(mav, "editedUser", EditUserProfileDto.class);
        assertEquals(dto.getFirstName(), user.getFirstName(), "First name is not equal");
        assertEquals(dto.getLastName(), user.getLastName(), "Last name is not equal");
        assertEquals(dto.getEmail(), user.getEmail(), "Last name is not equal");
    }

    @Test
    public void testEditProfile() throws Exception {
        User user = getUser();
        EditUserProfileDto userDto = getEditUserProfileDto();
        when(userService.editUserProfile(userDto.getEmail(), userDto.getFirstName(), userDto.getLastName(),
                userDto.getCurrentUserPassword(), userDto.getNewUserPassword(), userDto.getAvatar().getBytes()))
                        .thenReturn(user);
        BindingResult bindingResult = new BeanPropertyBindingResult(userDto, "editedUser");

        ModelAndView mav = controller.editProfile(userDto, bindingResult);

        String expectedUrl = "redirect:/user/" + user.getEncodedUsername() + ".html";
        assertViewName(mav, expectedUrl);
        verify(userService).editUserProfile(userDto.getEmail(), userDto.getFirstName(), userDto.getLastName(),
                userDto.getCurrentUserPassword(), userDto.getNewUserPassword(), userDto.getAvatar().getBytes());
    }

    @Test
    public void testEditProfileWithFailedValidation() throws Exception {
        User user = getUserWithoutAvatar();
        when(securityService.getCurrentUser()).thenReturn(user);
        EditUserProfileDto userDto = mock(EditUserProfileDto.class);
        when(userDto.getEmail()).thenReturn(EMAIL);
        when(userDto.getFirstName()).thenReturn(FIRST_NAME);
        when(userDto.getLastName()).thenReturn(LAST_NAME);
        when(userDto.getCurrentUserPassword()).thenReturn(PASSWORD);
        when(userDto.getNewUserPassword()).thenReturn(NEW_PASSWORD);
        when(userDto.getAvatar()).thenReturn(avatar);
        BindingResult bindingResult = mock(BindingResult.class);
        when(bindingResult.hasErrors()).thenReturn(true);

        ModelAndView mav = controller.editProfile(userDto, bindingResult);

        assertViewName(mav, "editProfile");
        verify(userService, never()).editUserProfile(userDto.getEmail(), userDto.getFirstName(),
                userDto.getLastName(), userDto.getCurrentUserPassword(), userDto.getNewUserPassword(),
                userDto.getAvatar().getBytes());
    }

    @Test
    public void testEditProfileWithNullAvatar() throws Exception {
        User user = mock(User.class);
        when(user.getAvatar()).thenReturn(new byte[0]);
        when(securityService.getCurrentUser()).thenReturn(user);
        EditUserProfileDto userDto = mock(EditUserProfileDto.class);
        when(userDto.getAvatar())
                .thenReturn(new MockMultipartFile("avatar", "", ImageFormats.JPG.getContentType(), new byte[0]));
        BindingResult bindingResult = mock(BindingResult.class);
        when(bindingResult.hasErrors()).thenReturn(true);

        ModelAndView mav = controller.editProfile(userDto, bindingResult);

        assertViewName(mav, "editProfile");
        verify(userDto).setAvatar(any(MultipartFile.class));
        verify(userService, never()).editUserProfile(any(String.class), any(String.class), any(String.class),
                any(String.class), any(String.class), Matchers.<byte[]>any());
    }

    @Test
    public void testEditProfileWithAvatarValidationFailed() throws Exception {
        User user = mock(User.class);
        when(user.getAvatar()).thenReturn(new byte[0]);
        when(securityService.getCurrentUser()).thenReturn(user);
        EditUserProfileDto userDto = mock(EditUserProfileDto.class);
        when(userDto.getAvatar()).thenReturn(
                new MockMultipartFile("avatar", "", ImageFormats.JPG.getContentType(), new byte[] { 1 }));
        BindingResult bindingResult = mock(BindingResult.class);
        when(bindingResult.hasErrors()).thenReturn(true);
        when(bindingResult.hasFieldErrors("avatar")).thenReturn(true);

        ModelAndView mav = controller.editProfile(userDto, bindingResult);

        assertViewName(mav, "editProfile");
        verify(userDto).setAvatar(any(MultipartFile.class));
        verify(userService, never()).editUserProfile(any(String.class), any(String.class), any(String.class),
                any(String.class), any(String.class), Matchers.<byte[]>any());
    }

    @Test
    public void testEditProfileDuplicatedEmail() throws Exception {
        EditUserProfileDto userDto = getEditUserProfileDto();
        BindingResult bindingResult = new BeanPropertyBindingResult(userDto, "editedUser");

        doThrow(new DuplicateEmailException()).when(userService).editUserProfile(userDto.getEmail(),
                userDto.getFirstName(), userDto.getLastName(), userDto.getCurrentUserPassword(),
                userDto.getNewUserPassword(), userDto.getAvatar().getBytes());

        ModelAndView mav = controller.editProfile(userDto, bindingResult);

        assertViewName(mav, "editProfile");
        assertEquals(bindingResult.getErrorCount(), 1, "Result without errors");
        verify(userService).editUserProfile(userDto.getEmail(), userDto.getFirstName(), userDto.getLastName(),
                userDto.getCurrentUserPassword(), userDto.getNewUserPassword(), userDto.getAvatar().getBytes());

        assertContainsError(bindingResult, "email");
    }

    @Test
    public void testEditProfileWrongPassword() throws Exception {
        EditUserProfileDto userDto = getEditUserProfileDto();
        BindingResult bindingResult = new BeanPropertyBindingResult(userDto, "editedUser");
        doThrow(new WrongPasswordException()).when(userService).editUserProfile(userDto.getEmail(),
                userDto.getFirstName(), userDto.getLastName(), userDto.getCurrentUserPassword(),
                userDto.getNewUserPassword(), userDto.getAvatar().getBytes());

        ModelAndView mav = controller.editProfile(userDto, bindingResult);

        assertViewName(mav, "editProfile");
        assertEquals(bindingResult.getErrorCount(), 1, "Result without errors");
        verify(userService).editUserProfile(userDto.getEmail(), userDto.getFirstName(), userDto.getLastName(),
                userDto.getCurrentUserPassword(), userDto.getNewUserPassword(), userDto.getAvatar().getBytes());
        assertContainsError(bindingResult, "currentUserPassword");
    }

    @Test
    public void testEditProfileValidationFail() throws Exception {
        User user = getUser();
        when(securityService.getCurrentUser()).thenReturn(user);

        EditUserProfileDto dto = getEditUserProfileDto();
        BindingResult bindingResult = mock(BindingResult.class);
        when(bindingResult.hasErrors()).thenReturn(true);

        ModelAndView mav = controller.editProfile(dto, bindingResult);

        assertViewName(mav, "editProfile");
        verify(userService, never()).editUserProfile(anyString(), anyString(), anyString(), anyString(),
                anyString(), Matchers.<byte[]>anyObject());
    }

    @Test
    public void testRemoveAvatar() throws IOException {
        User user = getUser();
        when(securityService.getCurrentUser()).thenReturn(user);
        ModelAndView mav = controller.removeAvatarFromCurrentUser();
        assertViewName(mav, "editProfile");
        verify(securityService).getCurrentUser();
        verify(userService).removeAvatarFromCurrentUser();
    }

    @Test
    public void testRenderAvatar() throws Exception {
        when(userService.getByEncodedUsername(ENCODED_USER_NAME)).thenReturn(getUser());
        HttpServletResponse response = mock(HttpServletResponse.class);
        ServletOutputStream servletOutputStream = mock(ServletOutputStream.class);
        when(response.getOutputStream()).thenReturn(servletOutputStream);
        controller.renderAvatar(response, ENCODED_USER_NAME);
        verify(response).setContentType("image/jpeg");
        verify(response).setContentLength(avatar.getBytes().length);
        verify(response).getOutputStream();
        verify(servletOutputStream).write(avatar.getBytes());
    }

    @Test
    public void testInitBinder() {
        WebDataBinder binder = mock(WebDataBinder.class);

        controller.initBinder(binder);

        verify(binder).registerCustomEditor(eq(String.class), Matchers.any(StringTrimmerEditor.class));
    }

    private void assertContainsError(BindingResult bindingResult, String errorName) {
        for (ObjectError error : bindingResult.getAllErrors()) {
            if (error != null && error instanceof FieldError) {
                assertEquals(((FieldError) error).getField(), errorName);
            }
        }
    }

    /**
     * @return RegisterUserDto with default field values
     */
    private RegisterUserDto getRegisterUserDto() {
        RegisterUserDto dto = new RegisterUserDto();
        dto.setUsername(USER_NAME);
        dto.setEmail(EMAIL);
        dto.setPassword(PASSWORD);
        dto.setPasswordConfirm(PASSWORD);
        dto.setFirstName(FIRST_NAME);
        dto.setLastName(LAST_NAME);
        return dto;
    }

    /**
     * @return {@link EditUserProfileDto} with default values
     */
    private EditUserProfileDto getEditUserProfileDto() {
        EditUserProfileDto dto = new EditUserProfileDto();
        dto.setEmail(EMAIL);
        dto.setFirstName(FIRST_NAME);
        dto.setLastName(LAST_NAME);
        dto.setCurrentUserPassword(PASSWORD);
        dto.setNewUserPassword(NEW_PASSWORD);
        dto.setNewUserPasswordConfirm(NEW_PASSWORD);
        dto.setAvatar(avatar);
        return dto;
    }

    private User getUser() throws IOException {
        User newUser = new User(USER_NAME, EMAIL, PASSWORD);
        newUser.setFirstName(FIRST_NAME);
        newUser.setLastName(LAST_NAME);
        newUser.setAvatar(avatar.getBytes());
        return newUser;
    }

    private User getUserWithoutAvatar() throws IOException {
        User newUser = new User(USER_NAME, EMAIL, PASSWORD);
        newUser.setFirstName(FIRST_NAME);
        newUser.setLastName(LAST_NAME);
        newUser.setAvatar(null);
        return newUser;
    }
}