首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在JUnit测试Java中替换Mockito以存根类

如何在JUnit测试Java中替换Mockito以存根类
EN

Stack Overflow用户
提问于 2018-01-12 17:33:55
回答 1查看 1.3K关注 0票数 2

在JUnit的测试会话中,我试图替换Mockito的正确用法,而不是对类进行存根。不幸的是,在web上有很多关于Mockito的教程,但是,对于存根方法,我想学习这种技术。

这项测试由Mockito进行:

代码语言:javascript
运行
复制
 @Test
public void addWrongNewUserSpaceInUsername() throws Exception {

    when(userValidator.isValidUsername(user.getUsername())).thenReturn(false);

    try {
        mockMvc.perform(
                post("/register")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(asJsonString(user)
                        ));
    } catch (Exception e) {
        Assert.assertTrue(e.getCause() instanceof UsernameNotValidException);
    }
}

为了澄清这些问题,所涉及的类别如下:

1)主计长

代码语言:javascript
运行
复制
   @RestController
public class UserController {

    @Autowired
    RepositoryUserDB repositoryUserDB;

    @Autowired
    UserValidator userValidator;

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public User createUser(@RequestBody User user) {


        if (userValidator.isValidUsername(user.getUsername())) {

            if(!userValidator.isValidPassword(user.getPassword())){
                throw new PasswordNotValidException();
            }

            if(userValidator.isValidDateOfBirth(user.getDateOfBirth()) == false){
                throw new DOBNotValidException();
            }

            // se lo user e' gia' presente
            if (repositoryUserDB.getUserByUsername(user.getUsername()) == null) {
                return repositoryUserDB.createUser(user);
            }
            throw new UsernameAlreadyExistException();
        } else throw new UsernameNotValidException();

    }
}

2)回购接口:

代码语言:javascript
运行
复制
public interface RepositoryUserDB {

    User getUserByUsername(String username);

    User createUser(User user);
}

3)回购:

代码语言:javascript
运行
复制
@Component

    public class MemoryUserDB implements RepositoryUserDB{

        Map<String, User> repo;

        public MemoryUserDB() {
            this.repo = new HashMap<>();
        }

        @Override
        public  User getUserByUsername(String username) {
            return repo.get(username);
        }

        @Override
        public User createUser(User user) {
            repo.put(user.getUsername(),user);
            return repo.get(user.getUsername());
        }
    }

4)清盘人:

代码语言:javascript
运行
复制
   @Component
public class UserValidator {

    public boolean isValidUsername(String username) {
        return username.matches("^[a-zA-Z0-9]+$");
    }

    public boolean isValidPassword(String pwd) {
        if (pwd == null)
            return false;
        return pwd.matches("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d){4,}.+$");
    }

    public boolean isValidDateOfBirth(String DOB) {
        return DOB.matches("^(?:(?:(?:0?[13578]|1[02])(\\/|-|\\.)31)\\1|(?:(?:0?[1,3-9]|1[0-2])(\\/|-|\\.)(?:29|30)\\2))(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$|^(?:0?2(\\/|-|\\.)29\\3(?:(?:(?:1[6-9]|[2-9]\\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\\/|-|\\.)(?:0?[1-9]|1\\d|2[0-8])\\4(?:(?:1[6-9]|[2-9]\\d)?\\d{2})$");
    }
}

5)ResEntityExceptionHandler

代码语言:javascript
运行
复制
    @ControllerAdvice
public class RestEntityExceptionHandler {

    @ExceptionHandler(UsernameNotValidException.class)
    @ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "username wrong")
    public void handleUsernameException() {
    }

    @ExceptionHandler(UsernameAlreadyExistException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "the username is already presents")
    public void handleUsername() {
    }

    @ExceptionHandler(PasswordNotValidException.class)
    @ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "password wrong")
    public void handlePasswordException() {
    }

    @ExceptionHandler(DOBNotValidException.class)
    @ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "Date Of Birth wrong")
    public void handleDOBException(){
    }

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-12 17:53:16

从理论上讲,对于用例来说,存根方法应该相当简单。

但是,由于您依赖使用Spring容器的Spring,所以设置起来非常困难,因为您应该找到一种方法,将模拟的bean注入容器中,以替换实际的bean:UserValidator

Spring测试中的模拟通常依赖于MockBean

这不是嘲笑,但不是太远。

要理解与Mockito模拟的不同,您可以参考to this question

使用框架提供了许多现成的功能,但也限制了您自己,因为您希望绕过框架特性。

假设您没有使用Spring执行集成测试,而是一个真正的单元测试(因此没有Spring引导容器),那么就可以这样执行。

与模拟UserValidator.isValidUsername()不同,您定义了UserValidator的自定义实现,该实现按照测试中预期的方式返回该方法。

最后,Mockito或任何模拟框架为您做了什么。

下面是存根类:

代码语言:javascript
运行
复制
public class UserValidatorStub extends UserValidator {

    private String expectedUsername;
    private boolean isValidUsername;

    public UserValidatorStub(String expectedUsername, boolean isValidUsername){
          this.expectedUsername = expectedUsername;
          this.isValidUsername = isValidUsername;
    }
    public boolean isValidUsername(String username) {
        if (username.equals(expectedUsername)){
           return isValidUsername;
        }
        // as fallback, it uses the default implementation but you may return false or null as alternative
       return super.isValidUsername(username);
    }

}

它接受一个构造函数来存储传递给存根方法的预期参数和返回的存根结果。

现在,在这里如何编写您的测试:

代码语言:javascript
运行
复制
 @Test
public void addWrongNewUserSpaceInUsername() throws Exception {

    // inject the mock in the class under test
    UserController userController = new UserController(new UserValidatorStub(user.getUsername(), false));
    try {
        userController.createUser(user);
    } catch (Exception e) {
        Assert.assertTrue(e.getCause() instanceof UsernameNotValidException);
    }
}

请注意,该示例依赖于UserController中的构造函数注入来设置依赖项。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48231332

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档