Java 如何为 REST Web 服务创建 JUnit 测试?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39513246/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:12:59  来源:igfitidea点击:

How to create a JUnit test for REST web service?

javaweb-servicesresttestingjunit

提问by CooperShelly

I am a beginner in JUnit. I want to create a test to get all the products and to get the products by id. This is my Java code:

我是 JUnit 的初学者。我想创建一个测试来获取所有products 并product通过id. 这是我的Java代码:

@Path("/produits")
@Produces("application/json")
public class ProduitResource {

    public ProduitResource() {
    }

    @GET
    public List<Produit> getProduits() {
        System.out.println("getProduits");

        return ReadXMLFile.getProduits();
    }

    @GET
    @Path("numProduit-{id}")
    public Produit getProduit(@PathParam("id") String numProduit) {
        System.out.println("getProduit");

        for (Produit current : ReadXMLFile.getProduits()) {
            if (numProduit.equals(current.getNumProduit())) {
                return current;
            }
        }
        return null;
    }

    @GET
    @Path("/search")
    public List<Produit> searchProduitsByCriteria(@QueryParam("departure") String departure, @QueryParam("arrival") String arrival, @QueryParam("arrivalhour") String arrivalHour) {
        System.out.println("searchProduitsByCriteria");

        return ReadXMLFile.getProduits().subList(0, 2);
    }
}

采纳答案by kaqqao

Presuming that what you want is to make a unit test, as opposed to an integration, functional or another type of test, you should simply instantiate ProduitResourceand run tests on it:

假设您想要的是进行单元测试,而不是集成、功能或其他类型的测试,您应该简单地实例化ProduitResource并对其运行测试:

@Test
public void testFetchingById() {
   ProduitResource repo = new ProduitResource();
   Produit prod = repo.getProduit("prod123");
   assertNotNull(prod);
   assertEquals(prod.getId(), "prod123");
}

Doing this might require mocking the environment, in your case you might need to mock whatever the Produits are being fetched from.

这样做可能需要模拟环境,在您的情况下,您可能需要模拟Produit从中获取 s 的任何内容。

If you were to actually fire HTTP requests at it, this would require a server running and would no longer constitute a unit test (as you'd be testing more than just this unit's own functionality). To do this, you could make your build tool start up the server before running tests (Jetty Maven pluginfor example can be used here to start Jetty in pre-integration-testphase), or you could make JUnit do it in a preparation step (@BeforeClass) as described here. Similar logic for shutting the server down (use post-integration-testphase in Maven or @AfterClassin JUnit).

如果您真的要向它发出 HTTP 请求,这将需要运行服务器并且不再构成单元测试(因为您将测试的不仅仅是该单元自己的功能)。为此,您可以让您的构建工具在运行测试之前启动服务器(例如,Jetty Maven 插件可以在此处用于分阶段启动 Jetty pre-integration-test),或者您可以让 JUnit 在准备步骤 ( @BeforeClass) 中执行此操作,如此处所述. 关闭服务器的类似逻辑(post-integration-test在 Maven 或@AfterClassJUnit 中使用阶段)。

There's many libraries that help you write the actual tests for RESTful resources, rest-assuredbeing a good one.

有许多库可以帮助您为 RESTful 资源编写实际测试,请放心,这是一个很好的库。

回答by J. Lenthe

There are two basic strategies that you can use (and you may want to do both).

您可以使用两种基本策略(您可能想同时使用这两种策略)。

  1. Redesign the code for your web service so you can mock out dependencies on any object that interacts with the environment, such as ReadXMLFile in your example. The mock objects would return canned data instead of reading any file or database. Use a mocking framework such as Mockito to make the creation of mock objects less effort. Then you can instantiate the ProductResource class in your JUnit tests and call it like any other Java code.

  2. Create JUnit set up and tear down methods (using @Before, @BeforeClass, @After, and @AfterClass annotations) that will set up a test environment, seed data, and deploy your application and clean it up when the tests are over. Then use a REST client API, such as Jersey client API or Spring RestTemplate, to call your web service and get the results.

  1. 重新设计您的 Web 服务的代码,以便您可以模拟与环境交互的任何对象的依赖关系,例如示例中的 ReadXMLFile。模拟对象将返回固定数据而不是读取任何文件或数据库。使用 Mockito 等模拟框架可以减少创建模拟对象的工作量。然后,您可以在 JUnit 测试中实例化 ProductResource 类,并像调用任何其他 Java 代码一样调用它。

  2. 创建 JUnit 设置和拆除方法(使用 @Before、@BeforeClass、@After 和 @AfterClass 注释),这些方法将设置测试环境、种子数据、部署应用程序并在测试结束后对其进行清理。然后使用 REST 客户端 API,例如 Jersey 客户端 API 或 Spring RestTemplate,调用您的 Web 服务并获取结果。

回答by Justas

As kaqqao mentioned, you can simply instantiate ProduitResourceand test it but in this case you won't be able to make HTTP call, check HTTP status. REST Assuredis suitable for testing REST service but problem is that you'll need to run it as separate instance which is not convenient - RestAssured testing without running Tomcat. Another option is to use Jersey Test (How to in-memory unit test Spring-Jersey) which provides ability to test REST service in-memory.

正如 kaqqao 提到的,您可以简单地实例化ProduitResource并测试它,但在这种情况下,您将无法进行 HTTP 调用,请检查 HTTP 状态。REST Assured适用于测试 REST 服务,但问题是您需要将其作为单独的实例运行,这很不方便 - RestAssured 测试不运行 Tomcat。另一种选择是使用 Jersey 测试(如何在内存中单元测试 Spring-Jersey),它提供了在内存中测试 REST 服务的能力。