Spring中的单元测试

简介: 这一章讲解如何使用 Spring 来整合测试框架,并且讲解单元测试在 Spring 下的最佳实践,Spring 团队非常注重测试驱动开发,Spring IoC 也可以使得测试变得非常简单。


一、概述



这一章讲解如何使用 Spring 来整合测试框架,并且讲解单元测试在 Spring 下的最佳实践,Spring 团队非常注重测试驱动开发,Spring IoC 也可以使得测试变得非常简单。


二、集成测试



集成测试最重要的一点是开发人员不需要将应用部署到服务器或者连接其他服务,就能将功能代码进行测试。

Spring 框架提供了spring-test模块,在org.springframework.test包下提供了在 Spring 容器中集成测试的类,测试不依赖任何服务器和其他部署环境,所以它比简单的单元测试慢,但比 Selenium 测试和部署到远程服务器上测试要快的多。


1. 常用注解


Spring 整合测试框架,提供了下面常用注解:


1.1@BootstrapWith


类级别注解,配置 Spring TestContext 框架如何引导启动,一般不用配置,使用默认的就行。


1.2@ContextConfiguration


类级别注解,集成测试中加载或配置ApplicationContext,使用locations参数指定基于XML配置的文件路径,使用classes参数指定基于注解配置的配置类。

@ContextConfiguration("/test-config.xml")
public class XmlApplicationContextTests {
    // class body...
}
@ContextConfiguration(classes = TestConfig.class)
public class ConfigClassApplicationContextTests {
    // class body...
}


1.3@WebAppConfiguration


类级别注解,集成测试中加载或配置WebApplicationContext,默认从file:src/main/webapp作为根路径加载 Web 应用资源。


1.4@ActiveProfiles


类级别注解,在集成测试中,激活 Spring 中定义 Profile 来加载ApplicationContext,Profile 详细用法参考文章Spring深入浅出IoC(下)

@ContextConfiguration
@ActiveProfiles({"dev", "integration"})
public class DeveloperIntegrationTests {
    // class body...
}


1.5@TestPropertySource


类级别注解,在集成测试中,指定 Spring 下的配置文件或配置属性。@TestPropertySource加载的配置属性优先级最高,比操作系统的环境变量,和使用@PropertySource注解声明的配置等优先级都要高,因此,如果这几种配置方式中存在相同的属性配置,则运行时会以优先级高的配置为准。

它支持指定 classpath 路径下的配置文件,或直接指定配置属性:

@ContextConfiguration
@TestPropertySource("/test.properties")
public class MyIntegrationTests {
    // class body...
}
@ContextConfiguration
@TestPropertySource(properties = { "timezone = GMT", "port: 4242" })
public class MyIntegrationTests {
    // class body...
}


3. 单元测试


我们后面演示 Spring 项目应用中,如何集成单元测试,使用最高效简单的操作来演示基本的单元测试操作。

第一步:模拟一个 Spring 应用程序。主要是配置一个ApplicationContext上下文,因为我们知道,项目中所有 Bean 的配置入口都是在ApplicationContext容器里面进行操作的。

package cn.codeartis.spring;
@Configuration
@ComponentScan
public class TestApplicationContext {
}

这里我们使用一个简单的基于注解配置的配置类,在该类同级目录下编写业务代码如下:

// 业务接口
package cn.codeartist.spring.service;
public interface DemoService {
    void service();
    void service(String str);
}
// 业务实现类
@Service
public class DemoServiceImpl implements DemoService {
    @Override
    public void service() {
        System.out.println("DemoServiceImpl.service");
    }
    @Override
    public void service(String str) {
        System.out.println("DemoServiceImpl.service::" + str);
    }
}

第二步:编写单元测试代码。如果我们在 Spring 项目中使用的集成测试框架是一样的,可以写一个抽象类为父类来作为配置全局测试框架的类。

package cn.codeartis.spring.test;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestApplicationContext.class)
public abstract class AbstractSpringRunnerTests {
}

这里我们指定了一个 Spring 的Runner和要测试的ApplicationContext上下文,对于熟悉 JUnit 测试工具的人来说对于Runner并不陌生,在该类同级目录下编写测试代码如下:

package cn.codeartis.spring.test.service;
public class DemoServiceTest extends AbstractSpringRunnerTests {
    @Autowired
    private DemoService demoService;
    @Test
    public void service() {
        demoService.service();
    }
}

此时一个简单的单元测试示例就完成了。


4. Mock功能


Spring 自带集成了Mockito工具,我们可以使用它来简单地实现业务代码的 Mock 功能,因为在业务中有调用第三方接口,或者使用微服务,而只想测试自己的业务代码,不管其他业务代码,就可以使用 Mock 来解决这个问题。假如我们对前面的测试代码进行 Mock,代码如下:

public class MockServiceTest extends AbstractSpringRunnerTests {
    @MockBean
    private DemoService demoService;
    @Before
    public void mock() {
        BDDMockito.doAnswer(invocation -> {
            System.out.println("Mock service.");
            return null;
        }).when(demoService).service();
    }
    @Test
    public void service() {
        demoService.service();
    }
}

Mockito 的功能很强大,还支持其他 Mock 场景,这里我们不详细讲,后面我们会有单独的文章来介绍。


5. JUnit特性


Spring Test 也支持 JUnit 的一些特性,比如:@Repeat@Timed等注解的使用,还有其他测试方式,但这里我们要注意,前面我们在 Spring 单元测试中使用的RunnerSpringRunner,当我们要在 Spring 中使用其他Runner时,需要通过JUnit中的Rule来实现,比如要在 Spring 中进行参数测试:

@RunWith(Parameterized.class)
public class DemoParameterizedTest extends AbstractSpringRunnerTests {
    @ClassRule
    public static final SpringClassRule springClassRule = new SpringClassRule();
    @Rule
    public final SpringMethodRule springMethodRule = new SpringMethodRule();
    @Parameterized.Parameter
    public String param;
    @Autowired
    private DemoService demoService;
    @Parameterized.Parameters(name = "{index}: {0}")
    public static String[] data() {
        return new String[]{"param1", "param2", "param3"};
    }
    @Test
    public void service() {
        demoService.service(param);
    }
}

此时需要在测试类中声明 Spring 提供的SpringClassRuleSpringMethodRule来集成 Spring 环境。

目录
相关文章
|
2月前
|
Java 测试技术 开发者
必学!Spring Boot 单元测试、Mock 与 TestContainer 的高效使用技巧
【10月更文挑战第18天】 在现代软件开发中,单元测试是保证代码质量的重要手段。Spring Boot提供了强大的测试支持,使得编写和运行测试变得更加简单和高效。本文将深入探讨Spring Boot的单元测试、Mock技术以及TestContainer的高效使用技巧,帮助开发者提升测试效率和代码质量。
221 2
|
4月前
|
XML Java 测试技术
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
这篇文章介绍了Spring5框架的三个新特性:支持@Nullable注解以明确方法返回、参数和属性值可以为空;引入函数式风格的GenericApplicationContext进行对象注册和管理;以及如何整合JUnit5进行单元测试,同时讨论了JUnit4与JUnit5的整合方法,并提出了关于配置文件加载的疑问。
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
|
2月前
|
存储 人工智能 Java
将 Spring AI 与 LLM 结合使用以生成 Java 测试
AIDocumentLibraryChat 项目通过 GitHub URL 为指定的 Java 类生成测试代码,支持 granite-code 和 deepseek-coder-v2 模型。项目包括控制器、服务和配置,能处理源代码解析、依赖加载及测试代码生成,旨在评估 LLM 对开发测试的支持能力。
48 1
|
3月前
|
JavaScript 前端开发 Java
Spring Boot+cucumber+契约测试
Spring Boot+cucumber+契约测试
25 0
Spring Boot+cucumber+契约测试
|
4月前
|
测试技术 Java Spring
Spring 框架中的测试之道:揭秘单元测试与集成测试的双重保障,你的应用真的安全了吗?
【8月更文挑战第31天】本文以问答形式深入探讨了Spring框架中的测试策略,包括单元测试与集成测试的有效编写方法,及其对提升代码质量和可靠性的重要性。通过具体示例,展示了如何使用`@MockBean`、`@SpringBootTest`等注解来进行服务和控制器的测试,同时介绍了Spring Boot提供的测试工具,如`@DataJpaTest`,以简化数据库测试流程。合理运用这些测试策略和工具,将助力开发者构建更为稳健的软件系统。
61 0
|
4月前
|
前端开发 Java 测试技术
单元测试问题之在Spring MVC项目中添加JUnit的Maven依赖,如何操作
单元测试问题之在Spring MVC项目中添加JUnit的Maven依赖,如何操作
|
5月前
|
Java 测试技术 开发工具
使用Spring Boot和Spock进行单元测试
使用Spring Boot和Spock进行单元测试
|
6月前
|
运维 Java 测试技术
Spring运维之boo项目表现层测试加载测试的专用配置属性以及在JUnit中启动web服务器发送虚拟请求
Spring运维之boo项目表现层测试加载测试的专用配置属性以及在JUnit中启动web服务器发送虚拟请求
49 3
|
6月前
|
Java Maven Spring
spring如何使用junit进行测试
spring如何使用junit进行测试
spring如何使用junit进行测试
|
6月前
|
Java 测试技术 持续交付
Java一分钟之-Spring Cloud Contract:契约测试
【6月更文挑战第16天】Spring Cloud Contract是微服务契约测试框架,通过DSL定义接口行为,使用WireMock生成存根进行独立开发验证。常见问题包括契约编写不清晰、未集成到CI/CD和契约版本控制混乱。例如,定义一个`GET /greeting`返回JSON响应的契约,Spring Cloud Contract会自动生成测试代码,帮助确保服务间接口一致性,提升开发效率和系统稳定性。
134 7