JUnit与Mockito详解:从入门到实战演练

495 阅读3分钟

单元测试与Mock框架详解:JUnit与Mockito实战

一、什么是单元测试?

单元测试是软件开发中最基础的测试类型之一,其目的是验证代码中最小可测试单元(如函数、类、方法等)是否按预期工作。

在Java世界中,JUnit 是最常用的单元测试框架,它提供了简洁的API来编写和运行测试用例。

JUnit 简介

JUnit 是一个开源的测试框架,主要用于 Java 应用程序的单元测试。目前主流版本为 JUnit 5。

常见注解说明
  • @Test:标记一个方法为测试方法。
  • @BeforeEach:在每个测试方法执行前运行。
  • @AfterEach:在每个测试方法执行后运行。
  • @BeforeAll:在所有测试方法执行前运行一次。
  • @AfterAll:在所有测试方法执行后运行一次。
示例代码
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {
    @Test
    void testAdd() {
        Calculator calculator = new Calculator();
        assertEquals(5, calculator.add(2, 3));
    }
}

二、Mock 框架简介

在实际开发中,我们常常需要测试某个类或方法的行为,但这些行为可能依赖于其他复杂的外部对象(如数据库、网络服务等)。为了隔离这些依赖,我们可以使用 Mock 对象

Mockito 是一个流行的 Mock 框架,它可以轻松地模拟对象并验证其行为。

Mockito 核心概念

  • Mocking:创建一个伪对象,用来替代真实对象。
  • Stubbing:定义 mock 对象的行为。
  • Verification:验证某些方法是否被调用。
示例代码
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

// 创建一个mock对象
List<String> mockedList = mock(List.class);

// 定义mock对象的行为
when(mockedList.get(0)).thenReturn("first");

// 使用mock对象
assertEquals("first", mockedList.get(0));

// 验证get方法是否被调用
verify(mockedList).get(0);

三、结合 JUnit 与 Mockito 的完整测试流程

我们将通过一个业务场景来展示如何将 JUnit 和 Mockito 结合使用。

场景描述:用户登录系统

假设我们有一个 UserService 类,它依赖于 UserRepository 接口来获取用户信息。

1. 定义接口
public interface UserRepository {
    User findUserById(int id);
}

public class User {
    private int id;
    private String name;

    // 构造器、getter/setter省略
}
2. 实现服务类
public class UserService {
    private UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public String getUserNameById(int id) {
        User user = userRepository.findUserById(id);
        return user != null ? user.getName() : "Unknown";
    }
}
3. 编写测试类
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

class UserServiceTest {
    private UserRepository mockRepo;
    private UserService userService;

    @BeforeEach
    void setUp() {
        mockRepo = mock(UserRepository.class);
        userService = new UserService(mockRepo);
    }

    @Test
    void testGetUserNameById() {
        // 准备数据
        User user = new User(1, "Alice");
        when(mockRepo.findUserById(1)).thenReturn(user);

        // 调用方法
        String result = userService.getUserNameById(1);

        // 断言结果
        assertEquals("Alice", result);

        // 验证方法调用
        verify(mockRepo).findUserById(1);
    }

    @Test
    void testGetUserNameWhenUserNotFound() {
        when(mockRepo.findUserById(999)).thenReturn(null);

        String result = userService.getUserNameById(999);
        assertEquals("Unknown", result);

        verify(mockRepo).findUserById(999);
    }
}

四、总结

通过本篇文章的学习,你应该已经掌握了以下内容:

  • 如何使用 JUnit 编写单元测试
  • 如何使用 Mockito 创建 Mock 对象并进行行为模拟
  • 如何在实际项目中应用这些工具进行自动化测试

如果你希望进一步提升代码质量与可维护性,强烈建议你在日常开发中坚持写单元测试,并熟练掌握 Mock 技术。

🚀 如果你有更多关于单元测试的问题,欢迎留言讨论!要不要?”