Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mocked repository returns null

I'm using springMVC and I would like to test my services but my @Mock repository is not working, so I will never get my user because my repository is null, how can I fix this problem? am I doing something wrong in my annotations?

Repository Interface:

package br.com.api.model.data;

import br.com.api.model.resources.User;

import java.util.List;

public interface UserDao {
    User findByLoginAndPassword(String login, String password);
    List<User> listAll();
}

Repository Implementation:

package br.com.api.model.repository;
import br.com.api.model.data.UserDao;
import br.com.api.model.resources.User;
import org.springframework.stereotype.Repository;

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


@Repository
public class UserRepository implements UserDao {

    public User findByLoginAndPassword(String login, String password) {
        System.out.println("lets find:");
        User userMatch = new User();
        List<User> users = usersMockup();

        for (User user : users) {
            if(user.getLogin().equals(login)
                    && user.getPassword().equals(password)){
                userMatch = user;
            }
        }

        return userMatch;
    }

    public List<User> listAll() {
        List<User> users = usersMockup();

        return users;
    }


    private List<User> usersMockup(){
        List<User> users = new ArrayList<User>();

        User first = new User();
        first.setLogin("first");
        first.setPassword("teste");

        User scnd = new User();
        scnd.setLogin("second");
        scnd.setPassword("teste");

        users.add(first);
        users.add(scnd);

        return users;
    }
}

This is my Service:

package br.com.api.model.services;


import br.com.api.model.data.UserDao;
import br.com.api.model.resources.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserDao userRepository;

    public User findUser(String login, String password) {
        User userMatch;
        userMatch = userRepository.findByLoginAndPassword(login, password);

        return  userMatch;
    }
}

Here is my Test:

package br.com.api.model.services;


import br.com.api.model.repository.UserRepository;
import br.com.api.model.resources.User;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.mockito.Mock;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.mockito.Mockito.when;

@RunWith(SpringJUnit4ClassRunner.class)
public class UserServiceTest {

    @Mock
    UserDao userRepository;

    @InjectMocks
    UserService userService;

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

    @Test
    public void findUser(){

        User user;
        user = userService.findUser("first", "teste");

        assertNotNull(user.getLogin());

    }

}  
like image 861
davidwillianx Avatar asked Mar 15 '16 01:03

davidwillianx


People also ask

Why is mock method returning null?

If a method return type is a custom class, a mock returns null because there is no empty value for a custom class. RETURN_MOCKS will try to return mocks if possible instead of null . Since final class cannot be mocked, null is still returned in that case.

What is the difference between @mock and @MockBean?

@Mock is used when the application context is not up and you need to Mock a service/Bean. @MockBean is used when the application context(in terms of testing) is up and you need to mock a service/Bean.

What is mock repository?

Mocking is a way to encapsulate your unit tests. If you want to test a service method you are not interested if the repository is working. For this you will write repository tests. Therefore you mock the repository call and tell which result should be returned to test your method in all possible situation.

What does mock do in Mockito?

mock() method allows us to create a mock object of a class or an interface. We can then use the mock to stub return values for its methods and verify if they were called. We don't need to do anything else to this method before we can use it. We can use it to create mock class fields, as well as local mocks in a method.


1 Answers

I believe you missed the whole idea of unit testing and mocking.

  1. When you are unit testing your UserService, you DO NOT want to use the real UserRepository implementation.
  2. You mocked a UserRepository, you do not expect the mock object to immediately behave as the real one. You need to make up its behavior (aka stubbing).
  3. You should rarely need to use Spring Runner in unit test.

In order to decide the behavior of the mock object, you gotta know the expected interaction of your system-under-test (SUT, which is the UserService in your case) and its dependencies (UserRepository)

In your case, the test should looks like (haven't compiled, just show you the idea)

public class UserServiceTest {

    @InjectMocks
    UserService userService;

    @Mock
    UserDao mockUserRepository;

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

    @Test
    public void testFindUser(){
        // Given
        User dummyUser = new User();
        when(mockUserRepository.findByLoginAndPassword(anyString(), anyString()).thenReturn(dummyUser);

        // When
        User result = userService.findUser("first", "teste");

        // Then
        // you are expecting service to return whatever returned by repo
        assertThat("result", result, is(sameInstance(dummUser)));

        // you are expecting repo to be called once with correct param
        verify(mockUserRepository).findByLoginAndPassword("first", "teste");
    }
}
like image 155
Adrian Shum Avatar answered Oct 06 '22 00:10

Adrian Shum