Java 模拟存储库返回 null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36001201/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 17:21:30  来源:igfitidea点击:

Mocked repository returns null

javaunit-testingspring-mvcmockito

提问by davidwillianx

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?

我正在使用 springMVC,我想测试我的服务,但我的 @Mock 存储库不起作用,所以我永远不会得到我的用户,因为我的存储库为空,我该如何解决这个问题?我在注释中做错了什么吗?

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());

    }

}  

采纳答案by Adrian Shum

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 UserRepositoryimplementation.
  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.
  1. 当你对你的 进行单元测试时UserService,你不想使用真正的UserRepository实现。
  2. UserRepository模拟了 a ,您不希望模拟对象立即表现得像真正的对象。你需要弥补它的行为(又名存根)。
  3. 您应该很少需要在单元测试中使用 Spring Runner。

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 UserServicein your case) and its dependencies (UserRepository)

为了决定模拟对象的行为,您必须知道被测系统(SUT,UserService在您的情况下是)的预期交互及其依赖项(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");
    }
}

回答by VdeX

Also you can pass name parameter like ,

您也可以传递名称参数,例如,

 @MockBean(name="userRepository")
 UserDao userRepository;