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

使用Mockito注入Mock Spring Repository时出现空指针异常

NullPointerException with @Autowired Field When Testing with Mockito

The Problem

I'm trying to test my DefaultRuleTester class, which has an @Autowired RuleChainRepository field. Every time I run the test, I get a NullPointerException pointing to that autowired field. I've tried using MockitoJUnitRunner and MockitoAnnotations.initMocks(this), but neither has fixed the issue.

Code Snippets

Under Test: DefaultRuleTester

@Component 
public class DefaultRuleTester implements RuleTester { 
    private static final Logger LOG = LogManager.getLogger(DefaultRuleTester.class); 
    @Autowired 
    RuleChainRepository ruleChainRepository; 

    public DefaultRuleTester() { } 

    @Override 
    public List<ResultChain> test(Entity entity) { 
        if (entity == null) return Collections.emptyList(); 
        try { 
            return selectAndTestAllRuleChains(entity); 
        } catch (InvalidClassException e) { 
            LOG.error("Unable to select RuleChains from database.", e); 
            return Collections.emptyList(); 
        } 
    } 

    protected List<ResultChain> selectAndTestAllRuleChains(Entity entity) throws InvalidClassException { 
        Collection<RuleChain> ruleChains = selectRuleChainsFromConnection(); 
        return testRuleChains(entity, ruleChains); 
    } 

    private Collection selectRuleChainsFromConnection() throws InvalidClassException { 
        Collection<RuleChain> ruleChains = ruleChainRepository.findAll(); 
        if (ruleChains == null) return Collections.emptyList(); 
        return ruleChains; 
    } 

    protected List<ResultChain> testRuleChains(Entity entity, Collection<RuleChain> ruleChains) { 
        // business logic 
    } 
}

Repository Definition: RuleChainRepository

public interface RuleChainRepository extends JpaRepository<RuleChain, Long> { }

Test Class: DefaultRuleTesterTest

@RunWith(MockitoJUnitRunner.class) 
public class DefaultRuleTesterTest { 
    private final Incident entity = new Incident(); 

    @InjectMocks 
    private DefaultRuleTester tester; 

    @Mock 
    private RuleChainRepository ruleChainRepository; 

    @Before 
    public void setUp() { 
        tester = new DefaultRuleTester(); 
    } 

    @Test 
    public void whenEntityTested_shouldReturnGivenResultChains() { 
        Mockito.when(ruleChainRepository.findAll()).thenReturn(singletonList(new RuleChainSpy())); 
        List<ResultChain> resultChains = tester.test(entity); 
        assert(1, resultChains.size()); 
    } 
}

Error Stack Trace

java.lang.NullPointerException 
at com.remsdaq.resque.officersubscription.entity_controller.DefaultRuleTester.selectRuleChainsFromConnection(DefaultRuleTester.java:30) 
at com.remsdaq.resque.officersubscription.entity_controller.DefaultRuleTester.selectAndTestAllRuleChains(DefaultRuleTester.java:25) 
at com.remsdaq.resque.officersubscription.entity_controller.DefaultRuleTester.test(DefaultRuleTester.java:17) 
at com.remsdaq.resque.officersubscription.entity_controller.DefaultRuleTesterTest.whenTested_shouldReturnGivenResultChains(DefaultRuleTesterTest.java:20) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:498) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) 
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) 
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79) 
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85) 
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39) 
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163) 
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) 
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) 
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) 
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

The Fix

Your issue is in the setUp method! You're manually creating a new DefaultRuleTester instance, which overwrites the one that Mockito already created and injected with your mock RuleChainRepository.

Step-by-Step Fix

  1. Remove the manual instance creation in setUp: Delete the line tester = new DefaultRuleTester();. Mockito will automatically create the tester instance and inject the mock repository for you.
  2. Fix the assertion syntax: Replace assert(1, resultChains.size()); with assertEquals(1, resultChains.size()); — the original syntax is invalid for Java's assert statement.

Here's the corrected test class:

@RunWith(MockitoJUnitRunner.class) 
public class DefaultRuleTesterTest { 
    private final Incident entity = new Incident(); 

    @InjectMocks 
    private DefaultRuleTester tester; 

    @Mock 
    private RuleChainRepository ruleChainRepository; 

    // Removed problematic setUp method

    @Test 
    public void whenEntityTested_shouldReturnGivenResultChains() { 
        Mockito.when(ruleChainRepository.findAll()).thenReturn(Collections.singletonList(new RuleChainSpy())); 
        List<ResultChain> resultChains = tester.test(entity); 
        assertEquals(1, resultChains.size()); 
    } 
}

Alternative Approach (If You Prefer Manual Instance Creation)

If you want to keep creating the instance manually, you'll need to inject the mock yourself using reflection (since Mockito can't inject into manually created instances automatically):

public class DefaultRuleTesterTest { 
    private final Incident entity = new Incident(); 

    private DefaultRuleTester tester; 

    @Mock 
    private RuleChainRepository ruleChainRepository; 

    @Before 
    public void setUp() { 
        MockitoAnnotations.initMocks(this);
        tester = new DefaultRuleTester();
        // Manually inject the mock using Spring's ReflectionTestUtils
        ReflectionTestUtils.setField(tester, "ruleChainRepository", ruleChainRepository);
    } 

    // Test method remains the same
}

The first approach (letting Mockito handle instance creation) is cleaner and recommended.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:20:18