java - 从远程 REST API 测试用例调用回滚数据库更改

标签 java spring-boot testing

我们的项目是使用 Spring Boot 构建的。在这个项目中,我们使用 java 语言构建了许多 REST API 实现,并且 REST API 可在 URI 端点调用。许多 REST API 实现都与后端的 RDBMS 数据库交互(我们使用 postgresql)。我们所有 REST API 的响应都是 JSON。

我正在编写 API 测试来测试这些 REST API,在测试用例中使用 java,并使用 JUnit 库来编写这些测试。

我正在编写两种 API 测试,如下所示,

1) 对于仅从数据库读取的 REST API,测试用例实现很简单。我在测试用例中使用来自 java 的 HTTP 客户端库,并发出 GET 或 POST 请求。然后,我对测试用例中返回的 JSON 响应执行“断言”。

2) 对于在数据库上执行创建、更新或删除操作之一的 REST API,我面临着从测试用例所做的数据库创建、更新或删除更改回滚的挑战。事实上,此时,我不知道如何在测试用例退出之前回滚测试用例所做的创建、更新或删除更改。谁能指点一下如何解决这个问题?

下面还提到了我的一个测试用例的当前源代码,



    import static org.junit.Assert.assertEquals;
    import static org.junit.Assert.assertTrue;

    import java.io.IOException;
    import java.io.InputStream;

    import org.apache.http.HttpResponse;
    import org.apache.http.HttpStatus;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.entity.ContentType;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.json.JSONArray;
    import org.json.JSONObject;
    import org.junit.After;
    import org.junit.AfterClass;
    import org.junit.Before;
    import org.junit.BeforeClass;
    import org.junit.Test;

    public class ApplnCommonRestControllerTest {
        private static String API_URI_2 = "http://localhost:8081/appln-restapis/rest/public/common/getalluniversities";
        private static CloseableHttpClient fHttpClient;

        @Before
        public void setUp() throws Exception {
            fHttpClient = HttpClients.createDefault();
        }

        @After
        public void tearDown() throws Exception {
            fHttpClient.close();
        }

        @Test
        public void getAllUniversitiesResponseBodyTest() throws ClientProtocolException, IOException {        
            HttpGet httpGet = new HttpGet(API_URI_2);
            HttpResponse httpResponse = fHttpClient.execute(httpGet);

            InputStream inpStream = (httpResponse.getEntity()).getContent();        
            String respBodyJsonString = Utilities.inputStreamToString(inpStream);
            JSONObject jsonResponeObj = new JSONObject(respBodyJsonString);
            JSONArray dataJsonArray = jsonResponeObj.getJSONArray("data");        

            assertTrue(dataJsonArray.length() >= 2);   // test that array contains at least two elements

            JSONObject arrElem = (JSONObject)dataJsonArray.get(0);   // test first element of array
            int univId = arrElem.getInt("id");
            String univName = arrElem.getString("universityname");
            assertTrue(univId == 1 && univName.length() > 0);

            arrElem = (JSONObject)dataJsonArray.get(dataJsonArray.length() - 1);   
            // test last element of array
            univId = arrElem.getInt("id");
            univName = arrElem.getString("universityname");
            assertTrue(univId > 1 && univName.length() > 0);        
        }
    }


上面的示例测试用例代码来 self 们的项目,执行 HTTP GET 数据库只读调用。我正在为测试用例寻找数据库回滚解决方案,以防测试用例调用的 REST API 执行数据库创建/更新/删除(即,在测试用例方法退出之前或之后,数据库创建/更新/删除更改应该回滚)。

最佳答案

一般来说,我倾向于将所有 @Test 方法标记为 @Transnational。但是,由于您的测试用例完全脱离应用程序上下文,这当然没有帮助。 spring有很棒的web层集成测试库MockMvc 。使用这个库,您的测试将如下所示:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.transaction.annotation.Transactional;

import static org.hamcrest.Matchers.*;

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class ApplnCommonRestControllerTest {
    @Autowired
    MockMvc mockMvc;
    @Test
    @Transactional
    public void getAllUniversitiesResponseBodyTest() throws Exception {
        mockMvc.perform(MockMvcRequestBuilders.get("/appln-restapis/rest/public/common/getalluniversities"))
                .andDo(MockMvcResultHandlers.print())
                .andExpect(MockMvcResultMatchers.jsonPath("$.data")
                        .value(iterableWithSize(2)))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].id", is(1)))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[0].universityname", not(emptyArray())))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[1].id", greaterThan(1)))
                .andExpect(MockMvcResultMatchers.jsonPath("$.data[1].universityname", not(emptyArray())));
    }
}

而且您的测试也会回滚,因为这并不是真正的外部 http 调用,并且 @Transactional 在这种情况下确实有效。

关于java - 从远程 REST API 测试用例调用回滚数据库更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60629506/

相关文章:

java - 有哪些工具可以分析 Java 中堆外的内存使用情况?

java - 使用抽象方法时定义的 var 为 null

java - 如何将 Spring 组件扫描限制为仅在我的 war 中的文件?

java - 测试 Java Spring @Scheduled 功能

java - 如何生成 1 次鼠标 + 1 次键盘点击?

java - Spring-Boot 错误页面映射和 NestedServletException

java - 为什么spring boot启动时会清除旧的日志配置

testing - 测试命令行工具的最佳方式?

multithreading - 集成多线程测试以对服务器进行压力测试

testing - 如何使用 Robot Framework 上传多个文件