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

如何对含Dagger注入的简单Repository做单元测试?遇空指针异常

解决UserRepository单元测试的NullPointerException问题

看起来你遇到的NPE核心原因很明确:单元测试环境下Dagger没有自动注入UserWebService实例——毕竟单元测试默认不会启动完整的依赖注入容器,导致mUserWebService一直是null,调用它的方法自然就抛出异常了。下面给你两种最常用的解决方案,按需选择:

方案1:用Mockito模拟WebService依赖(推荐纯单元测试场景)

单元测试的核心是隔离目标类的逻辑,不需要依赖真实的Web服务(哪怕它本身可用)。用Mockito模拟UserWebService是最合理的做法,步骤如下:

  1. 先添加Mockito依赖到你的测试gradle配置中(如果还没加):
testImplementation 'org.mockito:mockito-core:5.6.0'
testImplementation 'org.mockito:mockito-inline:5.6.0' // 支持模拟final类/接口
  1. 在测试类中模拟依赖并手动注入到Repository:
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import retrofit2.Call;
import retrofit2.Response;

import static org.mockito.Mockito.*;

public class UserRepositoryTest {

    @Mock
    private UserWebService mockUserWebService;
    @Mock
    private Call<UserResponse> mockCall;
    
    private UserRepository userRepository;

    @Before
    public void setUp() {
        // 初始化所有Mock对象
        MockitoAnnotations.openMocks(this);
        
        // 手动创建Repository并注入Mock依赖
        userRepository = new UserRepository();
        // 这里推荐给UserRepository加一个包级别的setter,或者用构造注入(更优雅,看下面的注意点)
        userRepository.setUserWebService(mockUserWebService);
        
        // 模拟WebService的getUser()返回预设的Call对象
        when(mockUserWebService.getUser()).thenReturn(mockCall);
        // 可以进一步模拟Call的执行结果,比如返回成功响应
        when(mockCall.execute()).thenReturn(Response.success(new UserResponse()));
    }

    @Test
    public void testGetUser_Success() throws Exception {
        // 调用Repository的目标方法
        userRepository.getUser();
        
        // 验证依赖方法是否被正确调用
        verify(mockUserWebService, times(1)).getUser();
        verify(mockCall, times(1)).execute();
    }
}

方案2:使用Dagger测试组件(集成测试场景)

如果你需要测试完整的依赖链,或者必须用真实的WebService实例,可以创建专门的Dagger测试组件:

  1. 编写测试用的Module,绑定测试环境的UserWebService:
@Module
public class TestUserModule {
    @Provides
    UserWebService provideUserWebService() {
        // 这里可以返回真实的WebService实例(测试环境地址),或者Mock对象
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://your-test-api-domain.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        return retrofit.create(UserWebService.class);
    }
}
  1. 创建测试组件:
@Component(modules = TestUserModule.class)
public interface TestUserComponent extends UserComponent {
    void inject(UserRepositoryTest test);
}
  1. 在测试类中初始化组件并完成注入:
public class UserRepositoryTest {

    @Inject
    UserWebService userWebService;
    
    private UserRepository userRepository;

    @Before
    public void setUp() {
        TestUserComponent component = DaggerTestUserComponent.create();
        component.inject(this);
        
        // 注入Repository的依赖
        userRepository = new UserRepository();
        userRepository.setUserWebService(userWebService);
    }

    // 编写你的测试方法...
}

额外优化建议

给UserRepository改用构造注入,这样测试时可以直接传入依赖,不用反射或setter,代码更优雅:

public class UserRepository {
    private final UserWebService mUserWebService;

    @Inject
    public UserRepository(UserWebService userWebService) {
        mUserWebService = userWebService;
    }

    // 你的业务方法...
}

测试时直接userRepository = new UserRepository(mockUserWebService)即可,非常方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:45:37