JUnit测试下的Given-When-Then

个人测试方面太过短板,没有形成一套良好的测试方法,测试技巧及常用JAVA,JS技术相关的测试框架使用,也很薄若。所以需要大量学习,大量实践。

最近看到一篇,关于JUnit测试下的测试技巧介绍,很不错,这里翻一下,正好理解下。

原文链接

在这里插入图片描述

我们看JUnit测试,有时会觉得很奇怪。因为我们必须Mock对象和结果,这需要大量的工作要做。虽然我们现在有很多先进的工具、框架,比如Mockito,PowerMock,但是利用它们写出的代码,有时,易读性,可理解和可维护性并没有想象的那么好。

结构化我们测试Case

这里有一个简单的策略来让我们的JUnit测试变得易读,并且不会有任何的副作用。
怎么做呢,划分下我们的测试,利用简单的注释将我们的测试分为三个部分,准备,执行,和校验。可能你会觉得,一篇博客就只是为了讲这么简单的一句话,未免有些小题大作了,但是,往往我们会在日常项目中迷失于此。

下面的代码片段就是一个例子,当然例子可能比实际的项目简单。但无论如何,你可以相信,这样的划分是可以帮助我们写好测试的。

/**
  * If an item is loaded from the repository, the name of that item should 
  * be transformed into uppercase.
  */
@Test
public void shouldReturnItemNameInUpperCase() {
 
    //
    // Given
    //
    Item mockedItem = new Item("it1", "Item 1", "This is item 1", 2000, true);
    when(itemRepository.findById("it1")).thenReturn(mockedItem);
 
    //
    // When
    //
    String result = itemService.getItemNameUpperCase("it1");
 
    //
    // Then
    //
    verify(itemRepository, times(1)).findById("it1");
    assertThat(result, is("ITEM 1"));

不同代码块的作用显而易见。不过我们还是总结下吧。

准备数据-》Given

这个部分,创建我们Mock的函数的返回值,或者我们将要测试方法的输入参数。此外,mock的方法也会在这个部分中准备。通常单元测试Case中,这个部分应该是最长,也是最复杂的。

注意:Mockito的when声明其实是given部分的,这点需要说明下,因为的确容易困惑。但,这与测试执行的准备工作有关,因此,放在这里最为合适。

执行-》When

这里一般只Call测试方法,这里标明了测试目的,因为这个部分的代码一般是最短的了。

验证-》Then

这个部分,执行环节的所有结果在这里得以声明。除此之外,也可以确认方法是否被执行。总之,主要的点,在这里进行Check。

测试Case的命名(测试方法)

早期测试方法都是以test为前缀,现在已经不怎么这样做了,一些同事喜欢用下划线去命名,我个人喜欢用驼峰命名。

当然,一个方法命名需要包含大量的信息,但可能这些信息更好的方式是放在测试代码的注释上。表明这个方法会发生什么,像shouldReturnItemNameInUpperCase ()这样,可能是个好的办法,显而易见,在项目开始前,大家统一测试方法规范是好的。

总结

这篇文章基本就结束了。再啰嗦两句,分享下个人对于测试的一点看法。为了去正确执行一个测试,有时为此准备大量的数据,是非常头疼的。尤其是如果在不同的测试Case,我们需要去Mock相同的一些方法或者数据,那么这个时候,我们做个类函数,去共享这些,这样会比较好,当然这些Mock对象因为影响着诸多的测试,所以也会越变越复杂,而且大量的测试这些对象。因此,在创建测试,Mock数据时,怎么做,如何做,我们需要权衡利弊,再三考虑。

写在最后

翻译下来,觉得通篇的确蛮简单的,但是正如作者所说,我们在实践中,却往往容易迷失。我这里也有一些自己项目上的思考、沉淀,这里抛砖引玉下。

  1. 下划线命名法
    无论是前端JS、TS项目还是后端Java项目,我们一致使用下划线命名法,前缀一般是should_xxx_when_xxx_given_xxx,这样做的好处,一是易读,二是,可以相对很长和准确的的表达测试,方法名对应我们测试Case中的then,when,given。
  2. 工具类来做到通用Mock数据
    对于复杂的数据,我们会采用JSON文件,程序反序列化来复用,当然如果大量的测试Case依赖于一份测试数据的话,确实会出现问题,比如改了这个测试数据,就会造成大面积的测试挂。这个就是个度的问题了。
    前后端,我们都会做一些builder,对测试Case提供基本的一些方法,数据轮子。
  3. Given-When-Then方法论适用于前后端测试,文章给与我们的是拆解测试方法,不要局限于JUnit这个框架,前端也通用,可能具体的技术造成写法的些许不同,但是请理解到骨子里去。
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 JUnit 测试 Java-Spark 可以按照以下步骤进行: 1. 在 pom.xml 文件中添加以下依赖项: ```xml <dependency> <groupId>com.sparkjava</groupId> <artifactId>spark-core</artifactId> <version>2.9.3</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.7.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.7.0</version> <scope>test</scope> </dependency> ``` 2. 创建一个测试类,并在类上使用 @ExtendWith(JUnit5.class) 注解。 3. 在测试类中创建一个 Spark 应用程序实例,并在该实例中设置路由。 ```java import static spark.Spark.get; public class SparkAppTest { private SparkApp app; @BeforeEach public void setup() { app = new SparkApp(); app.init(); // Define routes get("/hello", (req, res) -> "Hello World"); get("/hello/:name", (req, res) -> "Hello " + req.params("name")); } @AfterEach public void tearDown() { app.stop(); } @Test public void testHelloWorldRoute() { // Use JUnit assertions to test the route given().when().get("/hello").then().statusCode(200).body(is("Hello World")); } @Test public void testHelloNameRoute() { // Use JUnit assertions to test the route given().when().get("/hello/John").then().statusCode(200).body(is("Hello John")); } } ``` 4. 在测试方法中使用 RestAssured 发送 HTTP 请求,并使用 JUnit 断言来检查响应。 ```java import static io.restassured.RestAssured.given; import static org.hamcrest.Matchers.is; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import io.restassured.RestAssured; import spark.Spark; @ExtendWith(SparkExtension.class) public class SparkAppTest { private SparkApp app; @BeforeEach public void setup() { app = new SparkApp(); app.init(); // Define routes get("/hello", (req, res) -> "Hello World"); get("/hello/:name", (req, res) -> "Hello " + req.params("name")); } @AfterEach public void tearDown() { app.stop(); } @Test public void testHelloWorldRoute() { // Use JUnit assertions to test the route given().when().get("/hello").then().statusCode(200).body(is("Hello World")); } @Test public void testHelloNameRoute() { // Use JUnit assertions to test the route given().when().get("/hello/John").then().statusCode(200).body(is("Hello John")); } } ``` 以上就是使用 JUnit 测试 Java-Spark 的基本步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值