当前位置: 首页 > 知识库问答 >
问题:

构造函数注入上出现Nullpointer异常,并与字段注入mockito一起工作

冉德元
2023-03-14

我有一个抽象类,它有一个正在自动连接的依赖项:

public abstract class ClassB {
    @Autowired
    private ClassC classC;

    public String getValue() {
        classC.getSomeMethod();
    }
}

我有一个扩展这个抽象类的类:

@Component
public class ClassA extends ClassB {
    @Autowired
    private ClassD classD;

    public String getClassAMethod() {
        String value = getValue();
        String dReturn = classD.getD();
        return value + dReturn;
    }
}

现在,在进行单元测试时,我可以做到:

public class ClassATest {
    @Mock
    private ClassC classC;

    @Mock
    private ClassD classD;

    @InjectMocks
    private ClassA classA;

    @Test
    public void testSomething() {
        when(classC.getSometMethod()).thenReturn("classC");
        when(classD.getD()).thenReturn("classD");
        assertEquals(classA.getClassAMethod(), "classCclassD");
    }

}

这可以很好地工作,但是如果我对ClassA使用构造函数注入,则classC会出现空指针异常。

@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ClassA extends ClassB {
    private final ClassD classD;

    public String getClassAMethod() {
       String value = getValue();
       String dReturn = classD.getD();
       return value + dReturn;
    }
}

在第二种情况下,我甚至尝试用普通的构造函数调用替换InjectMocks,但ClassC对象没有被嘲笑。

堆栈跟踪:sun。反映NativeMethodAccessorImpl。sun上的invoke0(本机方法)。反映NativeMethodAccessorImpl。在sun上调用(NativeMethodAccessorImpl.java:62)。反映DelegatingMethodAccessorImpl。在java上调用(DelegatingMethodAccessorImpl.java:43)。郎。反思。方法在org调用(Method.java:498)。朱尼特。跑步者。模型FrameworkMethod$1。在org上运行ReflectiveCall(FrameworkMethod.java:50)。朱尼特。内部的跑步者。模型可反射。在org上运行(ReflectiveCallable.java:12)。朱尼特。跑步者。模型框架方法。在org上以开放方式调用(FrameworkMethod.java:47)。朱尼特。内部的跑步者。声明。调用方法。在org上评估(InvokeMethod.java:17)。朱尼特。内部的跑步者。声明。RunBefores。在org上评估(RunBefores.java:26)。朱尼特。跑步者。ParentRunner。runLeaf(ParentRunner.java:325)位于org。朱尼特。跑步者。BlockJUnit4ClassRunner。org上的runChild(BlockJUnit4ClassRunner.java:78)。朱尼特。跑步者。BlockJUnit4ClassRunner。org上的runChild(BlockJUnit4ClassRunner.java:57)。朱尼特。跑步者。ParentRunner 3美元。在org上运行(ParentRunner.java:290)。朱尼特。跑步者。ParentRunner 1美元。org上的时间表(ParentRunner.java:71)。朱尼特。跑步者。ParentRunner。org上的runChildren(ParentRunner.java:288)。朱尼特。跑步者。ParentRunner。在org上访问$000(ParentRunner.java:58)。朱尼特。跑步者。ParentRunner 2美元。在org上评估(ParentRunner.java:268)。朱尼特。跑步者。ParentRunner。在org上运行(ParentRunner.java:363)。莫基托。内部的跑步者。DefaultInternalRunner$1。在组织上运行(未知源)。莫基托。内部的跑步者。DefaultInternalRunner。在组织上运行(未知源)。莫基托。内部的跑步者。StrictRunner。在组织上运行(未知源)。莫基托。朱尼特。MockitoJUnitRunner。在组织上运行(未知源)。朱尼特。跑步者JUnitCore。在com上运行(JUnitCore.java:137)。intellij。junit4.JUnit4IdeaTestRunner。startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)位于com。intellij。rt.execution。朱尼特。IdeaTestRunner$中继器。startRunnerWithArgs(IdeaTestRunner.java:47)位于com。intellij。rt.execution。朱尼特。朱尼茨塔特。com上的prepareStreamsAndStart(JUnitStarter.java:242)。intellij。rt.execution。朱尼特。朱尼茨塔特。main(JUnitStarter.java:70)

共有1个答案

阎扬
2023-03-14

Lombok的@AllArgsConstructor@必需ArgsConstructor仅涵盖在类本身中声明的字段。来自超类的字段不被考虑,因为lombok无法访问这些类,因为它们在lombok在编译过程中运行时尚未解析。

因此,在您的情况下,为ClassA生成的构造函数只有ClassD class D作为参数,而没有ClassC class C。(您可以在IDE的类大纲视图中看到这一点,或者通过删除代码来看到。)因此,class C保持未初始化,从而导致NPE。

因此,不幸的是,lombok在您的情况下无法帮助您。您必须手动编写构造函数。

 类似资料:
  • 我把下面的内容看做是构造函数和setter注入的区别之一。有人能用一些简单的例子解释一下下面的区别吗,我对术语完全功能对象和不完全对象有点困惑。 -

  • 请帮助理解在哪种情况下我应该使用构造函数注入和设置器注入。请帮我举个合适的例子。 先谢谢你。

  • 注入是将依赖注入对象的过程。 构造函数注入很常见。 在此过程中,依赖项作为参数注入构造函数。 请参阅下面的示例。 创建一个名为GuiceTester的java类。 GuiceTester.java import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Inj

  • 问题内容: 假设我有一些类似以下的课程。(为简单起见,这是一个虚构类。) 由于我使用不同的实现,并且可能想对该发送功能进行单元测试,因此我认为我应该注入in 的方法。但是我该怎么做呢? 我见过的所有我理解的Guice示例似乎都是在构造函数中进行注入的: 但是我的类在其构造函数中接受了一个参数,我不想注入该参数。那我该怎么办呢? (注意:我是一个完整的Google Guice noob。我认为我了解

  • 我有一个用Mockito测试的类(PriceSetter),这个类有一个内部依赖项(一个数据库)。我想模拟这个内部依赖关系,然后将其注入类中,但在我的构造函数中没有指定依赖关系。因此,Mockito会自动尝试进行构造函数注入,而依赖项永远不会被注入。 我尝试在我的数据库对象上使用@mock,在我的PriceSetter类上使用@injectmocks,但是Mockito自动调用构造函数,它无法注入

  • 本文向大家介绍Design patterns 构造函数注入(C#),包括了Design patterns 构造函数注入(C#)的使用技巧和注意事项,需要的朋友参考一下 示例