全部产品

单元测试

更新时间:2020-05-14 18:17:32

SOFABoot 工程原型提供两类单元测试:

本文将以 SOFABoot Web 工程的测试类为例,对测试类的测试逻辑进行说明。

说明:SOFABoot Core 工程的测试类,测试逻辑比较简单,可参考 SOFABoot Web 工程,不再详细说明。

测试类路径:

  • 测试基类(AbstractTestBasesrc):projectName/app/web/src/main/test/java/.../base/AbstractTestBase.java
  • 测试子类(SofaRestServiceTest): projectName/app/web/src/main/test/java/.../usercases/SofaRestServiceTest.java

更多单元测试的资料可以参考 Spring Boot 官方文档

测试基类

示例代码

以下为默认生成的 AbstractTestBase.java 测试基类的示例代码:

  1. /**
  2. * 参考文档: http://docs.spring.io/spring-boot/docs/1.4.2.RELEASE/reference/htmlsingle/#boot-features-testing
  3. */
  4. @RunWith(SpringJUnit4ClassRunner.class)
  5. @SpringBootTest(classes = SOFABootWebSpringApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
  6. public abstract class AbstractTestBase {
  7. public static final String SOFA_REST_PORT = "8341";
  8. @Autowired
  9. public EmbeddedWebApplicationContext server;
  10. /**
  11. * 8080
  12. */
  13. @LocalServerPort
  14. public int definedPort;
  15. @Autowired
  16. public TestRestTemplate testRestTemplate;
  17. public String urlHttpPrefix;
  18. public String sofaRestHttpPrefix;
  19. @Before
  20. public void setUp(){
  21. sofaRestHttpPrefix = "http://localhost:" + SOFA_REST_PORT;
  22. urlHttpPrefix = "http://localhost:" + definedPort;
  23. childSetUp();
  24. }
  25. /**
  26. * 测试子类每个方法执行前需要进行的初始化代码放在此
  27. */
  28. public abstract void childSetUp();
  29. }

代码解读

  • @SpringBootTest 的参数:
    • SOFABootWebSpringApplication 类:是 SOFABoot 的启动函数。在运行单元测试时,能直接启动 SOFABoot 框架,并完成所有依赖中间件的自动配置和启动。
    • webEnvironment:用以配置 Servlet 环境。DEFINED_PORT 表示,该模式会提供一个真实的 Servlet 环境,使用内嵌的容器,但是使用定义好的端口。
  • 注入的 bean:
    • EmbeddedWebApplicationContext 实例:用于测试用户上下文。
    • TestRestTemplate 实例:用于测试 REST 功能的模板实例。

测试子类

示例代码

以下为默认生成的 SofaRestServiceTest.java 测试类的示例代码:

  1. public class SofaRestServiceTest extends AbstractTestBase {
  2. @Test
  3. public void testSofaRestGet() throws Exception {
  4. assertNotNull(testRestTemplate);
  5. String restUrl = sofaRestHttpPrefix + "/webapi/users/xiaoming";
  6. //注意:RestSampleFacadeResp 一定要有默认构造函数
  7. ResponseEntity<RestSampleFacadeResp> response = testRestTemplate.getForEntity(restUrl, RestSampleFacadeResp.class);
  8. RestSampleFacadeResp restSampleFacadeResp = response.getBody();
  9. assertTrue(restSampleFacadeResp.isSuccess());
  10. //注意:这里仅供测试使用,使用的是 jackson 不支持泛型的反序列化,所以被反序列化为 map。
  11. // 使用详情请参考文档:http://docs.spring.io/spring-boot/docs/1.4.2.RELEASE/reference/htmlsingle/#boot-features-testing
  12. Map<String, Integer> demoUserModel = (Map<String, Integer>) restSampleFacadeResp.getData();
  13. assertTrue(demoUserModel.get("userId") >= 0);
  14. }
  15. }

代码解读

  • 通过继承关系,子类可以从基类中获取下述信息:
    • 基类注入的 TestRestTemplate 实例
    • REST 端口号 8341
    • 待测试的 SOFAREST 的 URL:用来测试 SOFAREST 的功能,根据返回的数据结果进行校验
  • 测试逻辑
    • TestRestTemplate 会发起 restUrl 请求,并返回 response 对象。
    • response 对象通过 getBody() 方法,获取 restSampleFacadeResp 对象,通过 assertTrue() 方法对获取的数据进行判断。
    • restSampleFacadeResp 对象通过 getData() 方法,获取 SampleRestFacadeRestImpl 中的默认数据,并通过 assertTrue() 方法对获取的数据进行判断。
  • 测试结果验证

    • 方式 1:可以通过 IDEA 运行测试类 SofaRestServiceTest,通过测试时,控制台会提示:“Tests passed: 1 of 1 test”。
    • 方式 2:运行 SOFABootWebSpringApplication 类,然后在浏览器地址栏输入:http://localhost:8341/webapi/users/xiaoming,则输出结果如下图所示。

      单元测试

常见问题

项目正常启动,REST 无法正常访问,报错信息提示 processValue() 方法异常。

现象

  • 运行 SOFABootWebSpringApplication 类,项目正常启动。
  • 在浏览器地址栏输入:http://localhost:8341/webapi/users/xiaoming 后,没有输出结果。
  • 查看 /logs/rest/common-error.log ,有下述报错信息:
    1. [SOFA-REST-WORK-3-1] ERROR c.a.sofa.rest.server.netty.support.RequestHandler - Unexpected java.lang.NoSuchMethodError: com.alibaba.fastjson.serializer.JavaBeanSerializer.processValue(Lcom/alibaba/fastjson/serializer/JSONSerializer;Lcom/alibaba/fastjson/serializer/BeanContext;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;Ljava/lang/Integer

原因

上述错误主要是由于 Fastjson 版本 1.2.62 不兼容 1.2.60 以前的方法 JavaBeanSerializer.processValue 造成的。

解决方案

可以在主 pom.xml 中引入 fastjson 1.2.60 版本的依赖即可解决,示例如下:

  1. <dependency>
  2. <groupId>com.alibaba</groupId>
  3. <artifactId>fastjson</artifactId>
  4. <version>1.2.60</version>
  5. </dependency>