【问题标题】:Spring Boot - how to initialize class from a dependent module with injected dependenciesSpring Boot - 如何从具有注入依赖项的依赖模块初始化类
【发布时间】:2021-09-28 20:25:56
【问题描述】:

我有两个 Maven 项目 A 和 B,其中项目 B 嵌套在项目 A 中。结构如下所示:

Project A:
    src/test/java:
        MyTest.java
    Project B:
        src/test/java:
            MyNewTest.java
        pom.xml
    pom.xml

我的目标是让 MyNewTest.java 充当 MyTest.java 的包装器,并能够从 MyNewTest.java 调用在 MyTest.java 中声明的测试方法。 MyTest 有一些注入的依赖项。

我的问题是:如何在 MyNewTest 中初始化 MyTest 以确保 MyTest 的所有依赖都被正确注入?

MyTest 如下所示:

public class MyTest {
    
    @Autowired
    Service service; 

    @Autowired
    TestUtil util;

    Info info;
    
    @PostConstruct
    void init() {
        info = service.getStuff();
    }

    @Test
    public test1() {
        service.getMoreStuff();
        // more code omitted
    }
     
}

我尝试将@Component 添加到 MyTest,然后在 MyNewTest.java 中使用 @Autowired,如下所示:

public class MyNewTest {

    @Autowired
    private MyTest baseTest;

    @Test
    public void runTest() {
        // run the test in MyTest.java
        baseTest.test1();
    }
}

但这似乎不起作用 - baseTest 为空。我还尝试通过调用其默认构造函数来初始化 MyTest,但未能按预期注入依赖项。谁能建议一种初始化 MyTest.java 的正确方法,以便也注入它的所有依赖项?谢谢

【问题讨论】:

  • 在没有更多信息的情况下难以诊断。一个小问题,代码中的一个小错字 - 第一类是 MyTest 对吗?不是 MyNewTest。除了一个线索之外,如果一个自动装配的字段在启动后为空,那么包含该字段的实例不会包含在 Spring 应用程序上下文中,因为启动将失败,并出现与预期类型为 MyTest 的 bean 类似的错误。因此,要么 Spring 没有创建 MyNewTest 的实例(它的包是否在 ComponentScan 的范围内?),要么您引用了一个不在 applicationcontext 中的实例
  • 你怎么知道它是空的? NullPointerException 还是调试?当您的测试开始时,您是否看到 Spring Boot 启动了?关于其他线索的一些想法
  • 实际上,如果这些是需要在 Spring Boot 上下文中运行的测试类,我认为您需要将这些类注释为 SpringBootTest
  • @Chris 谢谢你,克里斯。是的,很抱歉第一堂课是 MyTest,我编辑过。我从调试和 NullPointerException 中都发现它为空。您能否详细说明 ComponentScan?我应该将 ComponentScan 添加到 MyNewTest 并指定 MyTest 的包吗?
  • 你有几个问题,第一个测试类不是 spring bean,因此你不能自动连接它们,第二个测试类不是为项目创建的工件的一部分(所以它们不是不在那里)。同样通常创建这样的依赖测试通常是一个非常糟糕的主意。

标签: java spring spring-boot dependency-injection


【解决方案1】:

您的测试的问题是 @Autowired 注释,因为没有触发 Spring 接线。您可以采取两种不同的方式来解决此问题。

第一个选项是在MyNewTest 中手动实例化baseTest,此时它将不再为空。但是,测试仍然会失败,因为您的两个 @Autowired 依赖项将为空。您可以添加设置器或通过构造函数注入它们。注意 - 如果您正在执行单元测试,应该模拟这些类。如果您选择通过构造函数添加这些类,它的外观如下 -

     private Service service;
     private TestUtil util;
     private MyTest baseTest;

     @BeforeEach
     void setUp() {
          service = mock(Service.class);
          util = mock(TestUtil.class);
          baseTest = new MyTest(service, util);
     }

第二个选项是向您的 Test 类添加配置以支持 Spring 布线。我不熟悉走这条路,因为我总是尽可能选择第一个选项。有多种方法可以添加 Spring 接线,但最简单的是-

@SpringBootTest
@RunWith(SpringRunner.class)
public class MyNewTest {

但是,这并不涵盖所有用例,因此您可能需要更具体的配置。您可以在这里找到一些可能的选项 - How to write JUnit test with Spring Autowire?

编辑-当我立即意识到一个问题时,我没有仔细阅读其余部分,我错过了这些是你试图连接在一起的测试类。我不确定这是否可能。

只有 Spring bean 可以@Autowired,因此第一步是尝试添加配置以使您的 Test 类成为 Spring bean。我以前从未听说过这样做,但很容易尝试。如果没有,您可以使用第一个选项来解决此问题。

第二个问题是测试不包含在工件中。我想您可以通过将您的测试课程与您的常规课程混合来规避这个问题,但这被认为是一种不好的做法。我从未听说过测试依赖于其他测试,但我猜这也是一种不好的做法。想要以这种方式创建测试的原因是什么?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-23
    • 2018-01-15
    • 2013-07-08
    • 2018-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多