首页  >  文章  >  web前端  >  消费者驱动的合同测试指南

消费者驱动的合同测试指南

Linda Hamilton
Linda Hamilton原创
2024-10-03 14:21:02491浏览

A Guide to Consumer-Driven Contract Testing
在现代微服务架构中,应用程序严重依赖服务间通信(通常通过 API)。确保这些 API 在开发期间和更改后继续按预期工作至关重要。实现这一目标的一种有效方法是通过消费者驱动的契约测试(CDCT)。 CDCT 是一种确保服务(生产者)遵守使用其 API 的服务(消费者)设定的期望的方法。

在本指南中,我们将探讨 CDCT 是什么、它是如何工作的、它在确保可靠的微服务交互方面的重要性,以及如何使用 Pact 等工具来实现它。

什么是消费者驱动的契约测试?
消费者驱动的合同测试是一种测试策略,可确保分布式架构中的服务之间的通信遵守商定的合同。它与传统的 API 测试不同,它关注消费者的需求,而不仅仅是确保 API 本身正常运行。 API 消费者和提供者之间的契约是由消费者的期望定义的,并且该契约根据提供者的实现进行验证。

关键术语:
• Consumer:使用API​​ 的服务。
• Provider(生产者):提供API的服务。
• 合同:消费者和提供者之间的正式协议,指定预期的 API 行为。

它是如何工作的?

  1. 消费者定义合约: 消费者定义其对提供者 API 应如何表现的期望(例如,其期望的端点、数据格式和响应状态代码)。
  2. 合同是共享的: 消费者与提供商共享此合同。该合同作为提供商必须满足的规范。
  3. 提供商验证合同: 提供商根据消费者的合同进行自我测试,确保其满足消费者的期望。
  4. 持续反馈循环: 对提供商 API 的任何重大更改都将被尽早发现,因为提供商必须根据所有消费者的合约进行验证。这创建了一个安全网,以确保提供者的变化不会对消费者产生负面影响。

消费者驱动的合约测试的重要性
在分布式架构中,尤其是微服务,管理服务之间的依赖关系变得更加复杂。 CDCT 通过多种方式帮助减轻这种复杂性:

1。防止生产中的破损
由于消费者定义了他们的需求,因此供应商 API 的更改如果不满足消费者的期望,就会在开发流程的早期被捕获。这降低了由于不兼容的更改而破坏生产系统的风险。

2。解耦开发
消费者驱动的契约测试允许消费者和提供商独立开发。当团队或服务单独发展时,这尤其有用。合约充当接口,确保集成按预期工作,无需在每个开发周期进行完整的集成测试。

3。更快的开发周期
通过 CDCT,消费者和提供商都可以并行开发和测试,从而加快开发速度。即使在消费者完全实现其功能之前,提供商也可以针对消费者的合约进行测试。

4。及早发现合同违规行为
在开发过程的早期检测到违反合同的提供商更改,使开发人员能够在问题变得严重之前解决问题。

如何实施消费者驱动的合约测试
有多种工具可用于实施 CDCT,其中 Pact 是最流行的工具之一。 Pact 允许消费者定义他们的合约并让提供商验证它们。

这是使用 Pact 实施 CDCT 的分步指南:
第 1 步: 定义消费者期望
首先,在消费者服务中,定义契约。这通常包括以下内容:
• 消费者将调用的端点。
• 请求方法(GET、POST、PUT 等)。
• 预期的请求正文或参数。
• 预期的响应正文和状态代码。
以下是在 JavaScript 中使用 Pact 在消费者测试中定义合约的示例:

const { Pact } = require('@pact-foundation/pact');
const path = require('path');

const provider = new Pact({
    consumer: 'UserService',
    provider: 'UserAPI',
    port: 1234,
    log: path.resolve(process.cwd(), 'logs', 'pact.log'),
    dir: path.resolve(process.cwd(), 'pacts'),
});

describe('Pact Consumer Test', () => {
    beforeAll(() => provider.setup());

    afterAll(() => provider.finalize());

    it('should receive user details from the API', async () => {
        // Define the expected interaction
        await provider.addInteraction({
            state: 'user exists',
            uponReceiving: 'a request for user details',
            withRequest: {
                method: 'GET',
                path: '/users/1',
                headers: {
                    Accept: 'application/json',
                },
            },
            willRespondWith: {
                status: 200,
                headers: {
                    'Content-Type': 'application/json',
                },
                body: {
                    id: 1,
                    name: 'John Doe',
                },
            },
        });

        // Make the actual request and test
        const response = await getUserDetails(1);
        expect(response).toEqual({ id: 1, name: 'John Doe' });
    });
});

在此示例中,消费者 (UserService) 希望提供者 (UserAPI) 在向 /users/1 发出 GET 请求时返回用户详细信息。

Step 2: Publish the Contract
Once the consumer test passes, Pact generates a contract file (Pact file) that can be shared with the provider. This contract can be stored in a Pact broker or a version control system so that the provider can use it for verification.

Step 3: Provider Verifies the Contract
The provider retrieves the contract and verifies that it complies with the consumer’s expectations. This is done by running a Pact test on the provider's side. Here’s an example of verifying a Pact contract in Java:

public class ProviderTest {

    @Test
    public void testProviderAgainstPact() {
        PactVerificationResult result = new PactVerifier()
            .verifyProvider("UserAPI", "pacts/UserService-UserAPI.json");

        assertThat(result, instanceOf(PactVerificationResult.Ok.class));
    }
}

The provider runs this test to ensure that it adheres to the contract specified by the consumer.

Step 4: Continuous Integration
Once CDCT is integrated into your CI/CD pipeline, each time a contract changes, the provider can automatically verify the contract. This ensures that API changes do not break the consumer’s expectations, providing a safety net for both teams.

CDCT Best Practices

  1. Small, Focused Contracts: Ensure that your contracts are small and focus only on the consumer’s needs. This prevents unnecessary complexity in the contract and simplifies verification.
  2. Contract Versioning: Always version your contracts. This allows providers to handle multiple versions of the same contract, helping you support different consumers at different stages of development.
  3. Independent Deployment: Ensure that CDCT is part of your CI/CD pipeline. Any changes to the consumer or provider should trigger contract tests to avoid breaking production environments.
  4. Use a Pact Broker: A Pact broker is a central repository that stores your contracts and allows both consumers and providers to retrieve them. It also provides a UI for visualizing contract versions and dependencies.

When to Use Consumer-Driven Contract Testing
CDCT is particularly useful when:
• You have microservices or distributed architectures with multiple services interacting.
• Teams working on different services need to develop independently without frequent integration testing.
• API contracts are likely to change often, and you want to avoid breaking consumer expectations.
• You need fast feedback loops to detect contract violations early in the development process.

Conclusion
Consumer-driven contract testing offers a reliable way to ensure that services in a distributed system communicate effectively without breaking changes. By focusing on consumer expectations and validating the provider against them, CDCT helps teams develop independently while ensuring stability. Whether you are building microservices, API-based applications, or distributed systems, incorporating CDCT into your testing strategy will improve the reliability and scalability of your services.

以上是消费者驱动的合同测试指南的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn