You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Mockito结合JUnit测试并Mock Java编写的GRPC服务

没问题!我来一步步教你怎么用Mockito结合JUnit测试你的gRPC Greeter服务,咱们分两种常见场景来看:

场景1:测试gRPC服务实现类(Mock依赖组件)

假设你已经有了GreeterServiceImpl这个服务实现类,它依赖了其他组件(比如UserService),我们要Mock这个依赖来测试服务的核心逻辑。

第一步:准备依赖

首先确保你的项目里包含了必要的测试依赖,以Maven为例,在pom.xml里添加这些:

<dependencies>
    <!-- JUnit 5核心依赖 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.9.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.9.2</version>
        <scope>test</scope>
    </dependency>
    <!-- Mockito支持 -->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>4.11.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>4.11.0</version>
        <scope>test</scope>
    </dependency>
    <!-- gRPC基础依赖 -->
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-netty-shaded</artifactId>
        <version>1.58.0</version>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-protobuf</artifactId>
        <version>1.58.0</version>
    </dependency>
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-stub</artifactId>
        <version>1.58.0</version>
    </dependency>
    <!-- gRPC测试工具,用来简化StreamObserver的测试 -->
    <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-testing</artifactId>
        <version>1.58.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

第二步:编写服务实现类示例

先给你一个典型的GreeterServiceImpl实现,它依赖了UserService来获取用户的完整名称:

public class GreeterServiceImpl extends GreeterGrpc.GreeterImplBase {
    private final UserService userService;

    public GreeterServiceImpl(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
        // 调用依赖的服务获取用户全名
        String fullUserName = userService.getFullName(request.getName());
        // 构建响应
        HelloReply reply = HelloReply.newBuilder()
                .setMessage("Hello, " + fullUserName + "!")
                .build();
        // 返回响应并结束流
        responseObserver.onNext(reply);
        responseObserver.onCompleted();
    }
}

// 假设的依赖服务接口
public interface UserService {
    String getFullName(String userId);
}

第三步:编写JUnit+Mockito测试类

现在我们来写测试类,Mock掉UserService,验证sayHello方法的逻辑是否正确:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import io.grpc.testing.TestStreamObserver;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.*;

@ExtendWith(MockitoExtension.class)
public class GreeterServiceImplTest {

    // Mock掉依赖的UserService
    @Mock
    private UserService userService;

    // 把Mock对象自动注入到被测试的服务实现类中
    @InjectMocks
    private GreeterServiceImpl greeterService;

    @Test
    void sayHello_ShouldReturnCorrectGreeting() {
        // 1. 准备测试数据
        String testUserId = "alice123";
        String expectedFullName = "Alice Smith";
        HelloRequest request = HelloRequest.newBuilder().setName(testUserId).build();

        // 2. 定义Mock对象的行为:当调用getFullName(testUserId)时返回预期的全名
        when(userService.getFullName(testUserId)).thenReturn(expectedFullName);

        // 3. 创建TestStreamObserver来捕获gRPC响应(gRPC测试工具提供的类,简化测试)
        TestStreamObserver<HelloReply> responseObserver = new TestStreamObserver<>();

        // 4. 调用被测试的方法
        greeterService.sayHello(request, responseObserver);

        // 5. 验证结果
        // 等待响应处理完成
        responseObserver.awaitCompletion();
        // 确保没有错误发生
        assertNull(responseObserver.getError());
        // 检查返回的消息是否符合预期
        HelloReply actualReply = responseObserver.getFirstValue();
        assertEquals("Hello, Alice Smith!", actualReply.getMessage());
    }
}
场景2:测试gRPC客户端(Mock服务端Stub)

如果你要测试调用gRPC服务的客户端代码,可以用MockitoMock掉gRPC的Stub对象,验证客户端是否正确调用了服务。

第一步:客户端代码示例

先看一个简单的gRPC客户端:

public class GreeterClient {
    private final GreeterGrpc.GreeterStub asyncStub;

    public GreeterClient(GreeterGrpc.GreeterStub asyncStub) {
        this.asyncStub = asyncStub;
    }

    public void sendGreeting(String userName, StreamObserver<HelloReply> responseObserver) {
        HelloRequest request = HelloRequest.newBuilder().setName(userName).build();
        // 调用gRPC服务
        asyncStub.sayHello(request, responseObserver);
    }
}

第二步:编写客户端测试类

用MockitoMockGreeterStub,验证客户端是否正确构造请求并调用Stub:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.verify;
import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(MockitoExtension.class)
public class GreeterClientTest {

    // Mock gRPC的异步Stub
    @Mock
    private GreeterGrpc.GreeterStub greeterStub;

    // Mock响应观察者
    @Mock
    private StreamObserver<HelloReply> responseObserver;

    // 注入Mock到客户端
    @InjectMocks
    private GreeterClient greeterClient;

    @Test
    void sendGreeting_ShouldCallStubWithCorrectRequest() {
        // 1. 准备测试数据
        String testUserName = "Bob";

        // 2. 调用客户端方法
        greeterClient.sendGreeting(testUserName, responseObserver);

        // 3. 捕获传递给Stub的参数,验证是否正确
        ArgumentCaptor<HelloRequest> requestCaptor = ArgumentCaptor.forClass(HelloRequest.class);
        ArgumentCaptor<StreamObserver<HelloReply>> observerCaptor = ArgumentCaptor.forClass(StreamObserver.class);

        // 验证Stub的sayHello方法被调用,并且参数符合预期
        verify(greeterStub).sayHello(requestCaptor.capture(), observerCaptor.capture());

        HelloRequest capturedRequest = requestCaptor.getValue();
        assertEquals(testUserName, capturedRequest.getName());
        assertEquals(responseObserver, observerCaptor.getValue());
    }
}
关键知识点总结
  • @ExtendWith(MockitoExtension.class):启用Mockito的JUnit 5支持,自动初始化Mock对象和注入依赖。
  • @Mock:创建一个Mock对象,替代真实的依赖组件或gRPC Stub。
  • @InjectMocks:自动将Mock对象注入到被测试类的构造方法或字段中。
  • TestStreamObserver:gRPC官方提供的测试工具,方便等待响应完成、获取响应结果和检查错误。
  • ArgumentCaptor:用来捕获传递给Mock方法的参数,验证参数的正确性。

内容的提问来源于stack exchange,提问作者Shreshtha Garg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:18:57