java - Mockito 测试抛出异常的 void 方法。 Spring Boot,eclipse IDE

标签 java spring exception junit mockito

如何测试抛出异常的 void 方法?

我在这里和其他页面上阅读了许多出版物,包括 Mockico 文档表格 https://javadoc.io/static/org.mockito/mockito-core/3.12.4/org/mockito/Mockito.html#5 .而我的测试仍然不会通过。我不知道自己做错了什么,我总是脸红。

可能与错误实现的异常类有关。

这是我的代码:

repo :

import org.springframework.data.jpa.repository.JpaRepository;

import succeed.app.start.model.User;

public interface UserRepository extends JpaRepository<User, Long> {

}

服务接口(interface):

public interface UserService {

    void deleteUserById(long userId);
}

服务实现:

@Service
public class UserServiceImpl implements UserService {

    private UserRepository userRepository;
    
    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public void deleteUserById(long userId) {
        userRepository.findById(userId).orElseThrow(() -> new ResourceNotFoundException("User", "ID", userId));
        
        userRepository.deleteById(userId);
    }
}

异常类:

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
    
    private final static long serialVersionUID = 1L;
    private String resourceName;
    private String fieldName;
    private Object fieldValue;
    
    public ResourceNotFoundException(String resourceName, String fieldName, Object fieldValue) {
        super(String.format("%s not found with %s : %s", resourceName, fieldName, fieldValue));
        this.resourceName = resourceName;
        this.fieldName = fieldName;
        this.fieldValue = fieldValue;
    }
    
    public String getResourceName() {
        return resourceName;
    }
    
    public String getFieldName() {
        return fieldName;
    }
    
    public Object getFieldValue() {
        return fieldValue;
    }
    
}

测试类:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.doThrow;

import succeed.app.start.exception.ResourceNotFoundException;
import succeed.app.start.repository.UserRepository;

@ExtendWith(MockitoExtension.class)
public class UserServiceImplTest {
    
    @Mock
    UserRepository userRepository;
    
    @Mock
    UserServiceImpl userService;
    
    
    @Test
    @DisplayName("Should throw ResourceNotFoundException when user doesn't exist.")
    void shouldThrowsResourceNotFoundException() {
        
        final long nonExistingId = 12902450235L;
        
        doThrow(new ResourceNotFoundException("User", "ID", nonExistingId)).when(userService).deleteUserById(nonExistingId);
        
        userService.deleteUserById(nonExistingId);
        
    }
    
}

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>succeed.app</groupId>
    <artifactId>start</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>start</name>
    <description>App to organize and achieve goals.</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter -->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

最佳答案

这里有一些错误。

首先,除了 @Display 注释中的消息外,您的测试并不真正期望抛出异常。您需要明确编码此行为,例如通过使用 assertThrows .

其次,您正在模拟 UserService,因此测试不会真正执行任何操作 - 在相同的方法中,您已经定义了一些假行为,然后对其进行了测试。相反,您应该模拟 UserRepository,然后测试 UserService 是否正确调用它:

@ExtendWith(MockitoExtension.class)
public class UserServiceImplTest {
    @Mock
    UserRepository userRepository;

    @InjectMocks
    UserServiceImpl userService;

    @Test
    @DisplayName("Should throw ResourceNotFoundException when user doesn't exist.")
    void shouldThrowsResourceNotFoundException() {
        final long nonExistingId = 12902450235L;

        doReturn(Optional.empty()).when(userRepository).findById(nonExistingId);
        assertThrows(
            ResourceNotFoundException.class,
            () -> userService.deleteUserById(nonExistingId));
    }
}

关于java - Mockito 测试抛出异常的 void 方法。 Spring Boot,eclipse IDE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68965256/

相关文章:

java - 如何从扩展可比较并实现通用接口(interface)的类创建实例?

java - Spring Aop 错误无法为此建议延迟构建 thisJoinPoint

java - Spring mvc 模块使用其他模块的资源文件

java - 将 <bean/> 代码转换为 @Bean

java - 从指定路径获取文件

java - GAE - 使用枚举字段和 'contains' 运算符过滤数据时 JDO 查询失败

java - 无法使用 log4j SMTP Appender 发送电子邮件。获取 "SMTPSendFailedException: 530 5.7.1 Authentication required"

c# - 当我可以安全地忽略它时,处理主键异常的正确方法是什么?

c# - 谁在 C# 中调用 Main() 方法? Main()方法异常时如何退出应用程序?

python - Python 解释器报告异常时给出意外行