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());
}
}
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.
@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.
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.
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.
I believe you missed the whole idea of unit testing and mocking.
UserService
, you DO NOT want to use the real UserRepository
implementation. UserRepository
, you do not expect the mock object to immediately behave as the real one. You need to make up its behavior (aka stubbing).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");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With