1

How to write a Junit, Mockito test case for binding result @Valid functionality with if-else conditions example?

@RequestMapping(value = "/scriptfile", method = RequestMethod.POST)     
public String create(
    @Valid ScriptFile scriptFile, 
    BindingResult result, 
    ModelMap modelMap
) 
{         
    if (scriptFile == null) 
        throw new IllegalArgumentException("A scriptFile is required"); 

    if (result.hasErrors()) {                 
        modelMap.addAttribute("scriptFile", scriptFile);                     
        modelMap.addAttribute("showcases", ShowCase.findAllShowCases());                     
        return "scriptfile/create";                 
    }             
    scriptFile.persist();             
    return "redirect:/scriptfile/" + scriptFile.getId();         
}   

How to write a Junitm Mockito test case for the above example?

Maciej Kowalski
  • 25,605
  • 12
  • 54
  • 63

4 Answers4

1

It will be something like this. You can use spy instead of mock if you can instantiate an object. Or even create a ModelMap instance and check if attributes are set properly instead of mocking.

@Mock
private BindingResult result;

@Mock
private ModelMap modelMap;

@Mock 
private ScriptFile scriptFile;

@BeforeMethod
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);
}

@Test(expectedExceptions = {IllegalArgumentException.class})  
public void shouldThrowIllegalArgumentException() {
    create(null, result, modelMap);
}

@Test
public void shouldPersistFile() {
    Mockito.when(result.hasErrors()).thenReturn(false);
    Mockito.when(scriptFile.getId()).thenReturn("FILE_ID");

    String output = create(scriptFile, result, modelMap);

    Mockito.verify(scriptFile, times(1)).persist();
    assertEquals("redirect:/scriptfile/FILE_ID", output)
}

@Test
public void shouldHandleErrors() {
    Mockito.when(result.hasErrors()).thenReturn(true);
    Mockito.when(scriptFile.getId()).thenReturn("FILE_ID");

    String output = create(scriptFile, result, modelMap);

    Mockito.verify(modelMap, times(2)).addAttribute(Mockito.any(), Mockito.any());
    assertEquals("scriptfile/create", output)
}
Michał Stochmal
  • 5,895
  • 4
  • 36
  • 44
  • I would: A) use @Mock instead of calling mock() in the before method. B) be sure to match his example. create() takes 3 arguments, not 1! C) emphasize that the goal must be to 1) test the public contract of the method and 2) on top of that, test all paths in the production class. Finally: I am wondering if it is really required to **mock** ModelMap. You only mock objects when the "normal" implementation can't be used. I would hope that one can simply pass in a map and configure it accordingly. – GhostCat Aug 18 '17 at 08:19
  • Thanks, I was writting it from just my memory without validating it with an IDE :). I don't think as well that ModelMap should be mocked, but without whole code I just can't tell. – Michał Stochmal Aug 18 '17 at 08:23
0

I would use mockito to mock both Binding result and the ScriptFile classes:

@Test
public void  create_WithErrors(){
    BindingResult bindingResult = Mockito.mock(BindingResult.class);
    BindingResult scriptFile = Mockito.mock(ScriptFile.class);
    Mockito.when(bindingResult.hasErrors()).thenReturn(true);
    String result = create(scriptFile, bindingResult, new ModelMap());
    Mockito.verify(bindingResult.hasErrors());
    Mockito.verify(scriptFile .persist(), Mockito.never());
    assertThat(result, is(equalTo("scriptfile/create")))
}
kimy82
  • 4,069
  • 1
  • 22
  • 25
0

Use spring-test MockMvC, there are plenty of existing code, one of them is :

Using Spring MVC Test to unit test multipart POST request

And your code snippet is not working, you are not binding the params (@RequestParam) also instead of @RequestMapping use @PostMapping

Thomas.L
  • 321
  • 1
  • 6
0

Here is an example for mockito test.

package com.ase.PRODUCTS.mockito.service;

import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ase.PRODUCTS.bean.AuthenticationStatus;
import com.ase.PRODUCTS.bean.SignUpStatus;
import com.ase.PRODUCTS.bean.User;
import com.ase.PRODUCTS.dao.UserDao;
import com.ase.PRODUCTS.repository.UserRepository;
import com.ase.PRODUCTS.service.UserService;

public class UserServiceTest {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceTest.class);

    @Mock
    UserRepository mockedUserRepository;
    // UserDao mockedUserDao;

    @InjectMocks
    UserService service;

    @Before
    public void setup() {

        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void signUpNewUser() {
        LOGGER.info("START : Inside Unit Testing addUser() method of UserServiceTest");
        User user = new User();
        user.setEmail("kiran@gmail.com");
        LOGGER.debug("User Object :  {}", user);
        when(mockedUserRepository.findUserByEmail(user.getEmail())).thenReturn(null);

        SignUpStatus expectedStatus = new SignUpStatus(true, false);
        SignUpStatus actualStatus = service.addUser(user);

        LOGGER.debug("Expected  Output :  {}", expectedStatus);
        LOGGER.debug("Actual  Output :  {}", actualStatus);

        Assert.assertEquals(true, expectedStatus.equals(actualStatus));
        verify(mockedUserRepository, times(1)).save(Mockito.any(User.class));
        verify(mockedUserRepository, times(1)).findUserByEmail(user.getEmail());

        LOGGER.info("End : Unit Testing addUser() method of UserServiceTest");
    }

    @Test
    public void emailAlreadyExists() {
        LOGGER.info("START : Inside Unit Testing addUser() method of UserServiceTest");
        User user = new User();
        user.setEmail("kiran@gmail.com");
        LOGGER.debug("User Object :  {}", user);
        when(mockedUserRepository.findUserByEmail(user.getEmail())).thenReturn(user);

        SignUpStatus expectedStatus = new SignUpStatus(false, true);
        SignUpStatus actualStatus = service.addUser(user);

        LOGGER.debug("Expected  Output :  {}", expectedStatus);
        LOGGER.debug("Actual  Output :  {}", actualStatus);

        Assert.assertEquals(true, expectedStatus.equals(actualStatus));
        verify(mockedUserRepository, times(0)).save(Mockito.any(User.class));
        verify(mockedUserRepository, times(1)).findUserByEmail(user.getEmail());

        LOGGER.info("End : Unit Testing addUser() method of UserServiceTest");
    }

    @Test
    public void loginValidUser() {
        LOGGER.info("START : Inside Unit Testing addUser() method of UserServiceTest");
        User user = new User();
        user.setEmail("kiran@gmail.com");
        user.setPassword("123456");
        LOGGER.debug("User Object :  {}", user);
        when(mockedUserRepository.findUserByEmail(user.getEmail())).thenReturn(user);

        AuthenticationStatus expectedStatus = new AuthenticationStatus();
        expectedStatus.setAuthenticated(true);
        expectedStatus.setActualUser(user);
        AuthenticationStatus actualStatus = service.loginUser(user);

        LOGGER.debug("Expected  Output :  {}", expectedStatus);
        LOGGER.debug("Actual  Output :  {}", actualStatus);

        Assert.assertEquals(true, expectedStatus.equals(actualStatus));
        verify(mockedUserRepository, times(0)).save(Mockito.any(User.class));
        verify(mockedUserRepository, times(1)).findUserByEmail(user.getEmail());

        LOGGER.info("End : Unit Testing addUser() method of UserServiceTest");
    }

    @Test
    public void testLoginForInvalidEmail() {
        LOGGER.info("START : Inside Unit Testing addUser() method of UserServiceTest");
        User user = new User();
        user.setEmail("kiran@gmail.com");
        user.setPassword("123456");
        LOGGER.debug("User Object :  {}", user);

        AuthenticationStatus expectedStatus = new AuthenticationStatus();
        expectedStatus.setAuthenticated(false);
        expectedStatus.setActualUser(null);

        User actualUser = new User();
        actualUser.setEmail("kiran.com");
        actualUser.setPassword("123456");

        when(mockedUserRepository.findUserByEmail(user.getEmail())).thenReturn(actualUser);

        AuthenticationStatus actualStatus = service.loginUser(user);

        LOGGER.debug("Expected  Output :  {}", expectedStatus);
        LOGGER.debug("Actual  Output :  {}", actualStatus);

        Assert.assertEquals(true, expectedStatus.equals(actualStatus));

        verify(mockedUserRepository, times(1)).findUserByEmail(user.getEmail());

        LOGGER.info("End : Unit Testing addUser() method of UserServiceTest");
    }

    @Test
    public void testLoginForInvalidPassword() {
        LOGGER.info("START : Inside Unit Testing addUser() method of UserServiceTest");
        User user = new User();
        user.setEmail("kiran@gmail.com");
        user.setPassword("123456");
        LOGGER.debug("User Object :  {}", user);

        AuthenticationStatus expectedStatus = new AuthenticationStatus();
        expectedStatus.setAuthenticated(false);
        expectedStatus.setActualUser(null);

        User actualUser = new User();
        actualUser.setEmail("kiran@gmail.com");
        actualUser.setPassword("1256");

        when(mockedUserRepository.findUserByEmail(user.getEmail())).thenReturn(actualUser);

        AuthenticationStatus actualStatus = service.loginUser(user);

        LOGGER.debug("Expected  Output :  {}", expectedStatus);
        LOGGER.debug("Actual  Output :  {}", actualStatus);

        Assert.assertEquals(true, expectedStatus.equals(actualStatus));

        verify(mockedUserRepository, times(1)).findUserByEmail(user.getEmail());

        LOGGER.info("End : Unit Testing addUser() method of UserServiceTest");
    }

}