优秀的编程知识分享平台

网站首页 > 技术文章 正文

Spring Boot中文参考指南(2.1.6) 46.3.6、使用 JMX

nanyue 2024-10-17 11:14:55 技术文章 5 ℃

上一篇[46.3、测试 Spring Boot 应用程序]

下一篇[46.3.11、自动配置的Spring WebFlux测试]

英文原文:https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-testing.html
GitHub:https://github.com/jijicai/Spring/tree/master/spring-boot

46.3.6、使用 JMX

由于测试上下文框架缓存上下文,因此默认情况下禁用 JMX 以防止相同的组件在同一域上注册。如果此类测试需要访问 MBeanServer,请考虑将其标记为脏(dirty):

@RunWith(SpringRunner.class)
@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
public class SampleJmxTests {

    @Autowired
    private MBeanServer mBeanServer;

    @Test
    public void exampleTest() {
        // ...
    }

}

46.3.7、模拟和监视 Beans

运行测试时,有时需要在应用程序上下文中模拟某些组件。例如,你可能在某个远程服务上有一个 facade,在开发期间该服务不可用。当你希望模拟在实际环境中可能难以触发的故障时,模拟也很有用。

Spring Boot 包含一个 @MockBean 注解,该注解可用于为应用上下文中的 bean 定义 Mockito 模拟。可以使用注解添加新 bean 或替换单个现有 bean 定义。注解可直接用于测试类、测试中的字段或 @Configuration 类和字段。在字段上使用时,也会注入创建的模拟的实例。mock bean 在每个测试方法后自动重置。

注释:

如果你的测试使用 Spring Boot 的测试注解之一(如 @SpringBootTest),则会自动启用此功能。要将此功能与其他安排一起使用,必须显式添加监听器,如下面示例所示:

@TestExecutionListeners(MockitoTestExecutionListener.class)

以下示例使用模拟(mock)实现替换现有的 RemoteService bean:

import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.mock.mockito.*;
import org.springframework.test.context.junit4.*;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

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

    @MockBean
    private RemoteService remoteService;

    @Autowired
    private Reverser reverser;

    @Test
    public void exampleTest() {
        // RemoteService has been injected into the reverser bean
        given(this.remoteService.someCall()).willReturn("mock");
        String reverse = reverser.reverseSomeCall();
        assertThat(reverse).isEqualTo("kcom");
    }

}

注释:@MockBean 不能用于模拟在应用程序上下文刷新期间执行的 bean 的行为。执行测试时,应用程序上下文刷新已完成,配置模拟行为为时已晚。在这种情况下,我们建议使用 @Bean 方法来创建和配置模拟。

另外,你可以使用 @SpyBean 将任何现有的 bean 与 Mockito spy 打包在一起。有关详细信息,请参阅 Javadoc。(https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/api/org/springframework/boot/test/mock/mockito/SpyBean.html )

注释:虽然 Spring 的测试框架在测试之间缓存应用程序上下文,并为共享相同配置的测试重用上下文,但 @MockBean 或 @SpyBean 的使用会影响缓存键, 这很可能会增加上下文的数量。

提示:如果你使用 @SpyBean 来监视带有 @Cacheable 方法的 bean,该方法按名称引用参数,则你的应用程序必须使用 -parameters 进行编译。这确保参数名称在 bean 被监视后可用于缓存基础设施。

46.3.8、自动配置的测试

Spring Boot 的自动配置系统适用于应用程序,但有时对测试来说可能有点太多。这通常有助于只加载测试应用程序 “切片” 所需的配置部分。例如,你可能想要测试 Spring MVC 控制器是否正确映射 URLs,并且你不想在这些测试中涉及数据库调用,或者你可能想要测试 JPA 实体, 当这些测试运行时,你对 web 层不感兴趣。

spring-boot-test-autoconfigure 模块包含许多注解,可用于自动配置此类 “切片”。它们中的每一个都以类似的方式工作,提供一个加载 ApplicationContext 的 @…Test 注解和一个或多个可用于自定义自动配置设置的 @AutoConfigure… 注解。

注释:每个切片将组件扫描限制为适当的组件,并加载一组非常受限制的自动配置类。如果你需要排除其中一个,大多数 @…Test 注解都提供了一个 excludeAutoConfiguration 属性。或者,你可以使用 @ImportAutoConfiguration#exclude。

注释:不支持在一个测试中使用多个 @…Test 注解来包含多个 “切片”。如果你需要多个 “切片”,请选择其中一个 @…Test 注解,并手动包含其他 “切片” 的 @AutoConfigure… 注解。

提示:也可以将 @AutoConfigure… 注解与标准的 @SpringBootTest 注解一起使用。如果你对应用程序的“切片”不感兴趣,但需要一些自动配置的测试 bean,则可以使用此组合。

46.3.9、自动配置的 JSON 测试

要测试对象 JSON 序列化和反序列化是否按预期工作,可以使用 @JsonTest 注解。@JsonTest 自动配置可用的受支持 JSON 映射器,该映射器可以是以下库之一:

(1)Jackson ObjectMapper、任何 @JsonComponent bean 和任何 Jackson Module

(2)Gson

(3)Jsonb

提示:可以在附录中找到由 @JsonTest 启用的自动配置的列表。(https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/test-auto-configuration.html)

如果需要配置自动配置的元素,可以使用 @AutoConfigureJsonTesters 注解。

Spring Boot 包括基于 AssertJ 的帮助器,它们与 JSONAssert 和 JsonPath 库一起工作,检查 JSON 是否如预期的那样出现。JacksonTester、GsonTester、JsonbTester 和 BasicJsonTester 类可以分别用于 Jackson、Gson、Jsonb 和 String。使用 @JsonTest 时,测试类上的任何帮助器字段都可以 @Autowired。以下示例展示了 Jackson 的测试类:

import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.json.*;
import org.springframework.boot.test.context.*;
import org.springframework.boot.test.json.*;
import org.springframework.test.context.junit4.*;

import static org.assertj.core.api.Assertions.*;

@RunWith(SpringRunner.class)
@JsonTest
public class MyJsonTests {

    @Autowired
    private JacksonTester<VehicleDetails> json;

    @Test
    public void testSerialize() throws Exception {
        VehicleDetails details = new VehicleDetails("Honda", "Civic");
        // Assert against a `.json` file in the same package as the test
        assertThat(this.json.write(details)).isEqualToJson("expected.json");
        // Or use JSON path based assertions
        assertThat(this.json.write(details)).hasJsonPathStringValue("@.make");
        assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make")
                .isEqualTo("Honda");
    }

    @Test
    public void testDeserialize() throws Exception {
        String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}";
        assertThat(this.json.parse(content))
                .isEqualTo(new VehicleDetails("Ford", "Focus"));
        assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford");
    }

}

注释:JSON 帮助器类也可以直接用于标准单元测试。为此,如果不使用 @JsonTest,请在 @Before 方法中调用帮助器的 initFields 方法。

如果你使用 Spring Boot 的基于 AssertJ 的帮助器在给定的 JSON 路径上对数字值进行断言,则可能无法根据类型使用 isEqualTo。相反,你可以使用 AssertJ 的 satisfies 来断言值与给定条件匹配。例如,下面的示例断言实际的数字是一个接近 0.15 的浮点值,偏移量为 0.01。

assertThat(json.write(message))
    .extractingJsonPathNumberValue("@.test.numberValue")
    .satisfies((number) -> assertThat(number.floatValue()).isCloseTo(0.15f, within(0.01f)));

46.3.10、自动配置的 Spring MVC 测试

要测试 Spring MVC 控制器是否按预期工作,请使用 @WebMvcTest 注解。@WebMvcTest 自动配置 Spring MVC 基础设施,并将扫描的 bean 限制为 @Controller、@ControllerAdvice、@JsonComponent、Converter、GenericConverter、Filter、WebMVCConfiguer 和 HandlerMethodArgumentResolver。使用此注解时,不扫描常规 @Component bean。

提示:可以在附录中找到由 @WebMvcTest 启用的自动配置设置的列表。(https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/test-auto-configuration.html )

提示:如果你需要注册额外的组件,比如 Jackson Module,你可以在测试中使用 @Import 来导入额外的配置类。

通常,@WebMvcTest 仅限于单个控制器,并与 @MockBean 结合使用,为所需的协作者提供模拟实现。

@WebMvcTest 也会自动配置 MockMvc。Mock MVC 提供了一种强大的方法来快速测试 MVC 控制器,而不需要启动完整的 HTTP 服务器。

提示:你还可以在非 @WebMvcTest(如 @SpringBootTest)中自动配置 MockMvc,方法是使用 @AutoConfigureMockMvc 对其进行注解。以下示例使用 MockMvc:

import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringRunner.class)
@WebMvcTest(UserVehicleController.class)
public class MyControllerTests {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    public void testExample() throws Exception {
        given(this.userVehicleService.getVehicleDetails("sboot"))
                .willReturn(new VehicleDetails("Honda", "Civic"));
        this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
                .andExpect(status().isOk()).andExpect(content().string("Honda Civic"));
    }

}

提示:如果你需要配置自动配置的元素(例如,当应用 servlet 过滤器时),你可以使用 @AutoConfigureMockMvc 注解中的属性。

如果使用 HtmlUnit 或 Selenium,自动配置还提供了一个 HTMLUnit WebClient bean 和/或一个 WebDriver bean。以下示例使用 HtmlUnit:

import com.gargoylesoftware.htmlunit.*;
import org.junit.*;
import org.junit.runner.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.boot.test.autoconfigure.web.servlet.*;
import org.springframework.boot.test.mock.mockito.*;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

@RunWith(SpringRunner.class)
@WebMvcTest(UserVehicleController.class)
public class MyHtmlUnitTests {

    @Autowired
    private WebClient webClient;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    public void testExample() throws Exception {
        given(this.userVehicleService.getVehicleDetails("sboot"))
                .willReturn(new VehicleDetails("Honda", "Civic"));
        HtmlPage page = this.webClient.getPage("/sboot/vehicle.html");
        assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic");
    }

}

注释:默认情况下,Spring Boot 将 WebDriver bean 放在一个特殊的“scope”中,以确保驱动程序在每次测试后退出,并注入新实例。如果你不想要这种行为,你可以将 @Scope("singleton") 添加到你的 WebDriver @Bean 定义中。

警告:Spring Boot 创建的 webDriver 范围将替换任何同名的用户定义范围。如果你定义自己的 webDriver 范围,你可能会发现在使用 @WebMvcTest 时它停止工作。

如果类路径上有Spring Security,@WebMvcTest 也将扫描 WebSecurityConfigurer bean。你可以使用 Spring Security 的测试支持,而不是完全禁用此类测试的安全性。有关如何使用 Spring Security 的 MockMvc 支持的更多详细信息,请参见第 80 章:使用 Spring Security 进行测试的操作指南部分。(https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/howto-use-test-with-spring-security.html )

提示:有时编写 Spring MVC 测试是不够的;Spring Boot 可以帮助你在实际的服务器上运行完整的端到端测试。(https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-with-running-server )

上一篇[46.3、测试 Spring Boot 应用程序]

下一篇[46.3.11、自动配置的Spring WebFlux测试]

Tags:

最近发表
标签列表