渐进集成单元测试

本文介绍了一种结合使用JUnit、Mockito、PowerMockito、SpringTest、Liquibase和H2进行高效单元测试的方法,同时提供了Maven配置示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JUnit

JUnit 短小精悍,运行单元测试效率高。

@Test
public void testInvalid() {
    Set<String> origins = new HashSet<>();
    origins.add(UserOriginEnum.LDAP.getDesc());
    origins.add("Sorry");

    boolean result = UserOriginEnum.isValid(origins);
    Assert.assertFalse(result);
}

Mockito

Mockito 短小精悍,运行单元测试效率高,能对不需要执行的方法(Feign接口,短信接口,Redis接口等)进行Mock。

@Mock
ApplicationEventPublisher applicationEventPublisher;

@InjectMocks
@Autowired
IamProjectServiceImpl iamProjectServiceImpl;


@Before
public void before() {
    iamProjectServiceImpl.setApplicationEventPublisher(applicationEventPublisher);

    Mockito.doAnswer(new Answer<Object>() {
        public Object answer(InvocationOnMock invocation) {
            Object[] args = invocation.getArguments();
            return "called with arguments: " + args;
        }
    }).when(applicationEventPublisher).publishEvent(Mockito.any());
}

PowerMockito

PowerMock 功能强大,是Mockito的增强版,支持私有和静态方法的Mock。

CustomUserDetails customUserDetails = new CustomUserDetails("summer","123456");
customUserDetails.setUserId(1L);
PowerMockito.mockStatic(DetailsHelper.class);
PowerMockito.when(DetailsHelper.getUserDetails()).thenReturn(customUserDetails);

SpringTest

SpringTest启动IOC容器和支持DI,能很好的集成JUnit、Mockito和PowerMockito,除了单元测试还支持接口测试。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {SteamTechApplication.class})
@Slf4j
public class RuanZhuControllerTest {
    @Autowired
    WebApplicationContext context;

    MockMvc mockMvc;

    @Autowired
    RuanZhuService ruanZhuService;

    @Autowired
    AttachmentService attachmentService;

    @Before
    public void setUp() {
        mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
    }

    @Test
    public void test_pageRuanZhu_firstPage() throws Exception {
        String url = String.format("/v1/site/ruan_zhu/page");
        log.info("请求URL:url={}", url);

        RuanZhuPageVO vo = RuanZhuPageVO.builder().build();
        //vo.setCurrent(2L);
        vo.setDesc("id");

        String response = mockMvc.perform(post(url).contentType(MediaType.APPLICATION_JSON).content(JSON.toJSONString(vo)))
                .andExpect(status().is(200))
                .andReturn().getResponse().getContentAsString();   //将相应的数据转换为字符串

        String responsePretty = JSON.toJSONString(JSON.parseObject(response), SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteDateUseDateFormat);

        log.info("返回报文:responsePretty={}", responsePretty);
    }
}

SpringTest 的奇淫技巧

  1. 启动指定注入类
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@SpringBootTest(classes = {DevSteamIamApplication.class, LiquibaseConfig.class})
@PrepareForTest(UserDetail.class)
@ActiveProfiles("dev")
@Slf4j
  1. 排除影响容器启动类
    exclude排除指定
@SpringBootApplication(
        scanBasePackages = {"com.test"},
        exclude = {EventAutoConfiguration.class, LiquibaseAutoConfiguration.class}
)
@MapperScan(basePackages = {"com.test.dao"})
@EnableFeignClients({"com.test.fegin", "com.test.api.feign", "com.test.starter"})
@EnableAsync
@EnableTransactionManagement
@Slf4j
public class DevSteamIamApplication {

    public static void main(String[] args) {
        EurekaEventHandler.getInstance().init();
        log.info("已开启EurekaEventHandler");
        SpringApplication.run(DevSteamIamApplication.class, args);
    }
}
  1. 全局替换
@TestConfiguration
public class TestStartUpConfig {
    @Bean
    public EventAutoConfiguration eventAutoConfiguration() {
        EventAutoConfiguration eventAutoConfiguration = Mockito.mock(EventAutoConfiguration.class);
        return eventAutoConfiguration;
    }

    @Bean
    public SyncIamGrantUserRoleEventListener syncIamGrantUserRoleEventListener() {
        SyncIamGrantUserRoleEventListener syncIamGrantUserRoleEventListener = Mockito.mock(SyncIamGrantUserRoleEventListener.class);
        return syncIamGrantUserRoleEventListener;
    }
}
  1. @MockBean来解决Feign接口Mock
@MockBean
OauthServiceClient oauthServiceClient;

ResponseEntity<Boolean> body = new ResponseEntity<>(Boolean.TRUE, HttpStatus.OK);
Mockito.when(oauthServiceClient.checkPassword(Mockito.any())).thenReturn(body);

Liquibase 和 H2

SpringBoot application.yml文件配置,SpringTest和 Liquibase、H2能无缝集合,对sit、uat和prod环境数据无任何污染。
有效的支持Devops,非常犀利的组合。

spring:
  datasource:
    platform: h2
    url: jdbc:h2:mem:test
    username: sa # 配置数据库用户名
    password: sa # 配置数据库密码
    driver-class-name: org.h2.Driver # 配置数据库驱动
  h2:
    console:
      path: /h2 # h2 console 访问路径
      enabled: true # 开启 console
      settings:
        web-allow-others: true # 允许远程访问
  liquibase:
    enabled: true
    change-log: classpath:/script/db/changelog-master.xml

Maven集成所有工具

SpringCloud Greenwich.RELEASE, SpringBoot 2.1.6.RELEASE

<!-- ========== Unit Test ========== -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>2.0.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>2.0.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
    <version>3.8.8</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
    <scope>test</scope>
</dependency>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值