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

JerseyTest结合Mockito模拟对象失效及匹配器错误求助

JerseyTest中Mockito模拟ServiceController失效的解决方案

1. 先搞定InvalidUseOfMatchers错误

这个错误大多是匹配器使用不规范导致的:

  • 必须静态导入Mockito的所有匹配器:import static org.mockito.Mockito.*;
  • 写when语句时,要么全用匹配器,要么全用具体参数,不能混着来。比如方法参数是单个字符串,就统一用anyString()或者具体值,别一半用匹配器一半用真实字符串。
  • 如果方法有多个参数,所有参数都得用匹配器,比如returnSth(String a, int b)就得写成when(mock.returnSth(anyString(), anyInt())).thenReturn(...),不能一个参数用匹配器另一个用具体数字。

2. 正确在JerseyTest里绑定Mock对象

Jersey有自己的DI容器,光靠Mockito的注解搞不定,得把Mock实例注册到Jersey的配置里:

步骤1:初始化Mock并配置行为

手动创建Mock比依赖注解更稳妥,避免JUnit和Jersey的Runner冲突:

public class HelloTest extends JerseyTest {
    private ServiceController mockService;

    @Override
    public void setUp() throws Exception {
        // 创建Mock实例
        mockService = mock(ServiceController.class);
        // 配置Mock返回固定值
        when(mockService.returnSth(anyString())).thenReturn("RetFromMock");
        super.setUp();
    }
}

步骤2:配置Jersey的资源绑定

重写configure方法,把Mock绑定到ServiceController类型,再注册Hello端点类:

@Override
protected Application configure() {
    return new ResourceConfig()
            // 绑定Mock实例到ServiceController类/接口
            .register(new AbstractBinder() {
                @Override
                protected void configure() {
                    // 如果ServiceController是接口,就to(ServiceController.class)
                    // 如果是具体类,同样绑定到自身类型
                    bind(mockService).to(ServiceController.class);
                }
            })
            // 注册你的端点类
            .register(Hello.class);
}

之前绑定报错IllegalArgumentException,大概率是绑定的实例类型和to()里的类型不匹配——比如你绑定了一个子类实例,却to到了无关的类,或者ServiceController是接口但你to到了实现类,改对应就行。

3. 避免NullPointerException的关键

  • 别指望@InjectMocks能自动搞定Jersey管理的资源类,因为Mockito的DI和Jersey的HK2容器是两套体系,容易出现注入失败。
  • 要么手动给Hello类注入Mock(比如用setter或者构造函数),要么通过上面的AbstractBinder让Jersey自动注入,二选一就行。
  • 如果非要用@Mock注解,一定要在setUp里调用MockitoAnnotations.openMocks(this)初始化,别光加注解不管初始化。

4. 完整可运行示例

import static org.mockito.Mockito.*;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.internal.inject.AbstractBinder;
import org.junit.Test;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import static org.junit.Assert.assertEquals;

public class HelloTest extends JerseyTest {
    private ServiceController mockServiceController;

    @Override
    public void setUp() throws Exception {
        mockServiceController = mock(ServiceController.class);
        // 配置Mock行为,确保匹配器使用正确
        when(mockServiceController.returnSth(anyString())).thenReturn("RetFromMock");
        super.setUp();
    }

    @Override
    protected Application configure() {
        return new ResourceConfig()
                .register(new AbstractBinder() {
                    @Override
                    protected void configure() {
                        bind(mockServiceController).to(ServiceController.class);
                    }
                })
                .register(Hello.class);
    }

    @Test
    public void testHelloEndpoint() {
        Response response = target("/hello").request().get();
        String result = response.readEntity(String.class);
        // 验证返回值是否符合预期
        assertEquals("Hello Jerseyreturned RetFromMock", result);
        // 验证Mock方法是否被调用过
        verify(mockServiceController).returnSth(anyString());
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:55:04