如何使用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
相关产品推荐
相关产品推荐

