我们的项目是使用 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/