Spring Boot 单元测试运行整个程序

Posted

技术标签:

【中文标题】Spring Boot 单元测试运行整个程序【英文标题】:Spring Boot unit test runs the whole program 【发布时间】:2020-07-09 01:53:15 【问题描述】:

我想用 Spring Boot 实现一个集成测试。我从spring-boot-starter-test 依赖项开始,版本2.2.5.RELEASE

我有以下组件:

@Component
public class MyMath 

    public int add(int a, int b) 
        return a + b;
    


主程序如下所示:

@SpringBootApplication
public class Main implements CommandLineRunner 

    public static void main(String[] args) 
        SpringApplication.run(Main.class, args);
    

    @Autowired
    private MyMath myMath;

    @Override
    public void run(String... args) throws Exception 
        System.out.println(myMath.add(2, 3));
    


它按预期工作 - 到目前为止,一切都很好。我想添加一个单元测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class MyMathTest 

    @Autowired
    private MyMath myMath;

    @Test
    public void testSaveAndList() 
        assertEquals(5, myMath.add(2, 3));
    


这也有效,但根据日志它执行整个程序。我不想运行程序本身,只想运行MyMath.add() 函数。我该怎么做?

到目前为止,我尝试了以下方法:

@RunWith(SpringJUnit4ClassRunner.class) 提供了相同的结果。 省略@SpringBootTest 结果NoSuchBeanDefinitionException。 重新格式化代码以使用 bean 而不是像下面这样的组件。

MyMath 无注解:

public class MyMath 

    public int add(int a, int b) 
        return a + b;
    


Main 保持不变。

@Configuration
public class AppConfig 

    @Bean
    public MyMath getMyMath() 
        return new MyMath();
    

还有测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class MyMathTest 

    @Autowired
    private MyMath myMath;

    @Test
    public void testSaveAndList() 
        assertEquals(5, myMath.add(2, 3));
    


所以我不能做的是在不运行整个程序的情况下测试一个组件。有什么可以帮助我的吗?谢谢!

【问题讨论】:

我认为你真的不需要 Spring 提供的任何东西来运行这个测试。尝试从测试类中删除所有与 Spring 相关的注释,不要注入 MyMath,而是在测试类的某处使用 new 实例化它。只要 @Test 注释仍然存在,JUnit 就应该选择它。尝试使用非 Spring 测试运行器,更多信息 here。 是的,测试一个 add 函数真的不需要任何 Spring 的东西。但是,如果我有一个具有自动装配依赖关系的组件,并且我想测试它怎么办?我故意不想让这个例子过于复杂。 【参考方案1】:

您无需重构代码。保持 MyMath 类的原样

@Component
public class MyMath 

    public int add(int a, int b) 
        return a + b;
    

像这样改变你的测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MyMath.class)
public class MyMathTest 

    @Autowired
    private MyMath myMath;

    @Test
    public void testSaveAndList() 
        assertEquals(5, myMath.add(2, 3));
    


如果您的 MyMath 类具有自动装配的其他依赖项,这会变得有点复杂。然后你必须使用模拟。

【讨论】:

谢谢,这正是我想要的!【参考方案2】:

如果您的 MyMath 类如此简单,我不会使用 Spring 来初始化它。没有必要,更重要的是 - junit 应该很快。因此,与其使用 Spring Context 运行测试,不如将其更改为简单的 JUnit 并像普通对象一样创建 MyMath:

public class MyMathTest 

    private MyMath myMath = new MyMath();

    @Test
    public void testSaveAndList() 
        assertEquals(5, myMath.add(2, 3));
    


【讨论】:

感谢您的回答。确实,我特意创造了这样一个简单的例子。这里的重点不是加法器,而是如何在 Spring 中创建单元测试。 如果你真的需要 Spring 来创建 JUnit 测试,你应该总是问这个问题。大多数情况下,您可以使用简单的构造函数创建对象,以便您的测试运行得更快。使用 SpringBootTest 注解的测试被认为是集成测试。

以上是关于Spring Boot 单元测试运行整个程序的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Boot 应用程序中运行 JUnit 单元测试而不提供数据源

无法在使用 @ExtendWith(SpringExtension.class) 运行的 Spring Boot 单元测试中注入应用程序上下文

编辑并重新运行 Spring Boot 单元测试,无需重新加载上下文以加快测试速度

如何防止我的 Spring Boot Batch 应用程序在执行测试时运行?

spring boot单元测试spring context重复加载问题

Spring Boot DataJpaTest 单元测试恢复到 H2 而不是 mySql