C#中实现契约测试的方法

 更新时间:2023年09月15日 09:02:19   作者:杨中科  
这篇文章主要介绍了C#中实现契约测试,在本文中,我将揭开契约测试的神秘面纱,并向您展示如何在 C# 项目中实现它,需要的朋友可以参考下

在软件开发中,确保微服务和API的可靠性和稳定性非常重要。 随着应用程序变得越来越复杂,对强大的测试策略的需求也越来越大,这些策略可以帮助团队在不牺牲敏捷性的情况下交付高质量的代码。 近年来获得广泛关注的一种方法是契约测试(Contract Testing)。 在本文中,我将揭开契约测试的神秘面纱,并向您展示如何在 C# 项目中实现它。

1. 术语

消费者(Consumer):对服务进行消费的代码,通常指的是客户端。

提供者(Provider): 提供服务的代码,通常指的是服务器端。

契约(Contract): 消费者和提供者之间商定的协议。 它包括预期的请求(输入)和响应(输出)。

2. 为什么需要契约测试?

构建和维护微服务是一项艰巨的任务。 在众多服务必须彼此无缝交互的世界中,确保对一项服务的更改不会破坏另一项服务的功能是很让人头疼的。 传统的集成测试针对的是整个系统之间的交互,工作量太大、速度太慢,甚至无法直接识别问题。 与之相反的是,契约测试侧重于测试各个服务之间的契约。 合同测试根据消费者和提供商之间商定的契约分别对消费者和提供商进行测试。

3. 如何执行契约测试

在契约测试中,消费者端程序员编写“消费者测试”,其中包含期望的输入和输出,并且期望将被保存到 Pact Json 文件中。 运行时,测试将请求发送到内置的模拟服务器而不是真实服务器,模拟服务器使用保存的 Pact Json 文件发送响应,该响应将用于验证消费者端测试用例。

此外,契约测试框架将读取保存的 Pact Json 文件,并向服务提供者(服务器)发送请求,并且将根据 Pact Json 文件中的预期输出来验证响应。

4. What is Pact?

Pact 是合约测试的实现。 由于消费者和提供者可能使用不同的编程语言进行开发,因此 Pact 是语言无关的,它支持多种编程语言,例如 Java、.NET、Ruby、JavaScript、Python、PHP 等。保存的 Pact Json 文件是由 用一种编程语言开发的消费者可以用来验证用另一种编程语言开发的提供者。

在本文中,消费者和提供者都是使用.NET (C#) 开发的。 Pact.Net 是 Pact 在 .Net 中的实现。

5. 如何使用Pact.Net?

使用Pact.Net总共分三步:开发一个待测试的WebAPI服务;编写消费者端测试用例;编写提供者端测试用例。

a. 开发待测试的WebAPI服务

创建一个 ASP.Net Core WebAPI项目,然后如下编写一个简单的控制器。

[ApiController]
[Route("[controller]/[action]")]
public class MyController : ControllerBase
{
    [HttpGet]
    public int Abs(int i)
    {
        return Math.Abs(i);
    }
}

上面的控制器提供了一个计算给定整数的绝对值的简单服务。

Pact需要使用ASP.Net Core项目的Startup类来启动Web服务器,但是,在最新的.NET Core中,传统的Startup.cs被Minimal API取代。如果 要将 Pact 与 .NET Core 一起使用,您必须切换到 传统Startup 风格的代码,如果您不知道如何切换回传统的Startup 风格的代码,请 搜索“Adding Back the Startup Class to ASP.NET Core”。

b. 编写消费者端测试用例

创建一个使用xUnit的.NET测试项目,然后在测试项目上安装“PactNet”这个Nuget包。然后编写如下的测试用例。

public class UnitTest1
{
    private readonly IPactBuilderV4 pactBuilder;
    public UnitTest1()
    {
        var pact = Pact.V4("MyAPI consumer", "MyAPI",new PactConfig());
        this.pactBuilder = pact.WithHttpInteractions();
    }
    [Fact]
    public async Task Test1()
    {
        this.pactBuilder.UponReceiving("A request to calc Abs")
            .Given("Abs")
            .WithRequest(HttpMethod.Get, "/My/Abs")
            .WithQuery("i","-2")//Match.Integer(-2) 
            .WillRespond()
            .WithStatus(HttpStatusCode.OK)
            .WithJsonBody(2);
        await this.pactBuilder.VerifyAsync(async ctx=>
        {
            using HttpClient httpClient = new HttpClient();
            httpClient.BaseAddress = ctx.MockServerUri;
            var r = await httpClient.GetFromJsonAsync<int>($"/My/Abs?i=-2");
            Assert.Equal(2,r);
        });
    }
}

“WithRequest().WithQuery()”用于定义输入,“WillRespond().WithJsonBody()”用于定义相应的预期输出。VerifyAsync中的代码片段是测试用例,根据“UponReceiving”定义的期望进行测试。 从“httpClient.BaseAddress = ctx.MockServerUri”可以看出,Provider 测试用例与 Pact 提供的Mock服务器交互而不是真实服务器进行交互。

接下来,让我们运行测试,测试运行完成后,测试项目的pact文件夹下会生成一个“MyAPI Consumer-MyAPI.json”,这个Json文件中保存了预期的输入和输出,如下图。

c. 编写提供者端测试用例

创建一个使用xUnit的.NET测试项目,然后向其安装 Nuget 包“PactNet”和“PactNet.Output.Xunit”。 由于提供程序测试必须使用 Startup 类启动测试服务器,因此请将待测试的 ASP.NET Core WebAPI 项目的引用添加到提供程序测试项目中。

创建一个“MyApiFixture”类,用于启动测试项目中测试的WebAPI服务器。MyApiFixture类的代码如下:

public class MyApiFixture: IDisposable
{
    private readonly IHost server;
    public Uri ServerUri { get; }
    public MyApiFixture()
    {
        ServerUri = new Uri("http://localhost:9223");
        server = Host.CreateDefaultBuilder()
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseUrls(ServerUri.ToString());
                webBuilder.UseStartup<Startup>();
            })
            .Build();
        server.Start();
    }
    public void Dispose()
    {
        server.Dispose();
    }
}

接下来,如下创建一个使用保存的Pact Json文件对服务器(提供者)进行测试的测试用例。

public class MyApiTest1: IClassFixture<MyApiFixture>
{
    private readonly MyApiFixture fixture;
    private readonly ITestOutputHelper output;
    public MyApiTest1(MyApiFixture fixture,ITestOutputHelper output)
    {
        this.fixture = fixture;
        this.output = output;
    }
    [Fact]
    public async Task Test1()
    {
        var config = new PactVerifierConfig
        {
            Outputters = new List<IOutput>
            {
                new XunitOutput(output),
            },
        };
        string pactPath = Path.Combine("..","..","..","..",
            "TestConsumerProject1", "pacts", "MyAPI consumer-MyAPI.json");
        using var pactVerifier = new PactVerifier("MyAPI", config);
        pactVerifier
            .WithHttpEndpoint(fixture.ServerUri)
            .WithFileSource(new FileInfo(pactPath))
            .Verify();
    }
}

“pactPath”是指保存的Pact文件,在您的项目中,它会根据项目名称、相对路径的不同而不同。 执行上述测试时,Pact 将启动测试项目中的测试服务器,发送请求并根据保存的 Json 文件验证响应。

6. 对基于消息的服务使用Pact

Pact也支持对于基于消息的服务(也被称为async API)进行测试。详细请查看Pact文档的“messaging pacts”部分。

到此这篇关于C#中实现契约测试的方法的文章就介绍到这了,更多相关C#契约测试内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解C#借助.NET框架中的XmlTextReader类读取XML的方法

    详解C#借助.NET框架中的XmlTextReader类读取XML的方法

    这篇文章主要介绍了详解借助.NET框架中的XmlTextReader类读取XML的方法,这种方式的执行效率还是比较令人满意的,需要的朋友可以参考下
    2016-04-04
  • C#操作INI文件的辅助类IniHelper

    C#操作INI文件的辅助类IniHelper

    这篇文章主要为大家详细介绍了C#操作INI文件的辅助类IniHelper,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-03-03
  • C#获取指定目录下指定文件的方法

    C#获取指定目录下指定文件的方法

    这篇文章介绍了C#获取指定目录下指定文件的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • 深入c# GDI+简单绘图的具体操作步骤(三)

    深入c# GDI+简单绘图的具体操作步骤(三)

    前两篇已经基本向大家介绍了绘图的基本知识.那么,我就用我们上两篇所学的,做几个例子.我们先来做一个简单的--仿QQ截图
    2013-05-05
  • c# 获得当前绝对路径的方法(超简单)

    c# 获得当前绝对路径的方法(超简单)

    下面小编就为大家分享一篇c# 获得当前绝对路径的方法(超简单),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01
  • C# 使用Proxy代理请求资源的方法步骤

    C# 使用Proxy代理请求资源的方法步骤

    这篇文章主要介绍了C# 使用Proxy代理请求资源的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • C#使用foreach语句遍历堆栈(Stack)的方法

    C#使用foreach语句遍历堆栈(Stack)的方法

    这篇文章主要介绍了C#使用foreach语句遍历堆栈(Stack)的方法,涉及C#操作foreach实现遍历堆栈的技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • c#接口使用示例分享

    c#接口使用示例分享

    接口与抽象类一样,也是表示某种规则,一旦使用了该规则,就必须实现相关的方法。对于C#语言而言,由于只能继承自一个父类,因此若有多个规则需要实现,则使用接口是个比较好的做法
    2014-02-02
  • c#项目实现发布到服务器全过程

    c#项目实现发布到服务器全过程

    这篇文章主要介绍了c#项目实现发布到服务器全过程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • Unity实现刮奖效果

    Unity实现刮奖效果

    这篇文章主要为大家详细介绍了Unity实现刮奖效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-10-10

最新评论