【问题标题】:How to test Rest-APIs that rely on persistence with arquillian如何使用 arquillian 测试依赖持久性的 Rest-API
【发布时间】:2015-11-18 15:34:42
【问题描述】:

我想测试一个通过 JAX-RS 提供休息端点的类。此类依赖于 JPA EntityManager ,因此依赖于需要在测试执行之前填充的数据库。我看到了像 dbunit 这样的数据库填充解决方案,但我想直接从我的测试类填充数据(或通过object mother pattern 委托)。但是在测试其他端点时,我需要使用注释选项@Deployment(testable = false),它拒绝将EntityManager 注入我的测试类。

那么我该如何解决这种情况呢?

或者有没有更好的最佳实践? (也许是嘲笑,但黑盒测试也不可能)

【问题讨论】:

    标签: java rest jpa jax-rs


    【解决方案1】:

    您可以创建一个 bean 来生成您的测试数据:

    @Startup
    @Singleton
    public class TestDataGenerator {
    
        @PersistenceContext
        private EntityManager em; 
    
        @PostConstruct
        private void generateTestData() {
            // Generate your test data
        }
    }
    

    上面定义的TestDataGenerator 类用@Singleton(确保只有一个类的实例)和@Startup(用于在应用程序启动序列期间的急切初始化)进行注释。

    TestDataGenerator 类添加到您的 Arquillian 部署中:

    @RunWith(Arquillian.class)
    public class MyArquillianTest {
    
        private Client client = ClientBuilder.newClient();
    
        @Deployment
        @RunAsClient
        public static WebArchive createDeployment() {
            return ShrinkWrap.create(WebArchive.class)
                .addClasses(TestDataGenerator.class, ...)
                .addAsResource("test-persistence.xml", "META-INF/persistence.xml")
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
        }
    
        @Test
        public void testAPI(@ArquillianResource URL deploymentUrl) {
            // Test your REST service
            WebTarget target = client.target(deploymentUrl.toURI()).path("api");
        }
    }
    

    注意@RunAsClient 等价于@Deployment(testable = false)

    @ArquillianResource 注释允许您注入 URL 来测试您的 Web 应用程序。

    【讨论】:

    • 这是一个有趣的方法。但是,我想知道由于将测试数据生成器与要测试的源代码混合在一起,这是否可以被视为不好的做法。此外,每个测试用例都必须有一个特定的生成器 bean。我想要一个能够创建一组通用测试数据的对象母亲,然后可以在测试类本身中对其进行自定义。
    • @thomas.mc.work 由于您有不同的源文件夹来存储您的应用程序 (src/main) 和您的测试 (src/test),并且您将 src/test 内容仅用于测试目的,这种方法可以正常工作。您只是在创建一个应该进行测试的部署文件并将您的测试数据嵌​​入其中。在generateTestData() 方法中,您可以将测试数据的生成委托给您的对象母亲。
    【解决方案2】:

    对于测试,我通常尝试将黑盒测试和单元测试完全分开(我想这是你如何做的偏好)。

    例如,我的 REST Api 可以依赖它想要的任何东西,但通常它不会做太多事情,而是调用我的数据库层或某种访问我的数据库层的外观。对象是注入的,是的,但通常我将字段包设为私有,这意味着您可以从同一个包中设置它们(也适用于 Junit)。

    例如:

    public class Facade1 {
    @Inject
    Facade facade;
    
    public void doSomething() { ... }
    
    }
    

    这个类代表我的 REST API。我可以通过简单地添加一个模拟对象作为外观来测试 doSomething。请注意,这是一个非常无用的测试,但你明白了。单元测试应该尽可能多地进行独立测试。

    现在测试实际的 Rest API 我通常求助于 python 集成测试器。 Python 有很好的 http 库,可以让您非常轻松地发出请求。

    为此,我为我的 Rest Server 设置了一个暂存环境。环境是用于测试的类似现场的表示。那里的一切都需要工作,并且需要与生产部署在同一版本上。

    然后我使用 python 戳我的 REST Api 并验证响应。由于我已经设置了暂存环境,因此我可以完全控制数据库内容。因此,我很容易测试所有响应是否正确。

    我的典型流程是:

    1. 编译
    2. 构建
    3. 部署
    4. 集成测试

    我希望这会有所帮助。如果您想要更清晰的示例,您可能需要发布更多代码,因为我很难想象您到底想做什么:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-04
      • 2021-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 1970-01-01
      相关资源
      最近更新 更多