自动测试ApiController

本文关键字:ApiController 自动测试 | 更新日期: 2023-09-27 18:16:15

我有一个ApiController,想用单元测试来测试它,包括路由。

一个例子:

[RoutePrefix("prefix")]
public class Controller : ApiController
{
    [HttpGet]
    [Route("{id1}")]
    public int Add(int id1, [FromUri] int id2)
    {
        return id1 + id2;
    }
}

我现在想测试这个方法。我明白了,我可以像普通方法一样测试它。但是我还想通过将URL转换为方法参数来测试它。

基本上我想有一个自动测试,我调用一个URL,如prefix/10?id2=5,并得到15的结果。这有可能吗?

自动测试ApiController

我为内存集成测试编写了一个小助手类,它可以作为测试套件的一部分调用。

internal interface IHttpTestServer : IDisposable {
    HttpConfiguration Configuration { get; }
    HttpClient CreateClient();
}
internal class HttpTestServer : IHttpTestServer {
    HttpServer httpServer;
    public HttpTestServer(HttpConfiguration configuration = null) {
        httpServer = new HttpServer(configuration ?? new HttpConfiguration());
    }
    public HttpConfiguration Configuration {
        get { return httpServer.Configuration; }
    }
    public HttpClient CreateClient() {
        var client = new HttpClient(httpServer);
        return client;
    }
    public void Dispose() {
        if (httpServer != null) {
            httpServer.Dispose();
            httpServer = null;
        }
    }
    public static IHttpTestServer Create(HttpConfiguration configuration = null) {
        return new HttpTestServer(configuration);
    }
}

然后像这样使用

[TestMethod]
public async Task HttpClient_Should_Get_OKStatus_From_InMemory_Hosting() {
    using (var server = new HttpTestServer()) {
        MyWebAPiProjectNamespace.WebApiConfig.Configure(server.Configuration);
        var client = server.CreateClient();
        string url = "http://localhost/prefix/10?id2=5";
        var expected = 15;
        var request = new HttpRequestMessage {
            RequestUri = new Uri(url),
            Method = HttpMethod.Get
        };
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        using (var response = await client.SendAsync(request)) {
            Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
            var result = await response.Content.ReadAsAsync<int>();
            Assert.AreEqual(expected, result);
        }
    }
}

这将配置一个内存测试服务器,测试可以使用它的httpclient对其进行调用。它本质上是一个端到端的集成测试。

  1. 使用Microsoft ASP创建OWIN StartUp类。. NET Web API 2.2 OWIN包:

    public class Startup
    { 
        public void Configuration(IAppBuilder builder)
        {
            var config = new HttpConfiguration();
            builder.UseWebApi(config);
            config.MapHttpAttributeRoutes();
            config.EnsureInitialized();
        }
    }
    
  2. 使用Microsoft ASP。测试中的。NET Web API 2.2 Self Host包(例如使用NUnit):

    [Test]
    [TestCase(10, 5, 15)]
    [TestCase(1, 2, 3)]
    // add your test cases
    public async Task AdditionTests(int a, int b, int result) 
    {
        // Arrange
        var address = "http://localhost:5050";
        using (WebApp.Start<Startup>(address))
        {
            var client = new HttpClient();
            var requestUri = $"{address}/prefix/{a}?id2={b}";
            // Act
            var response = await client.GetAsync(requestUri);
            // Assert
            Assert.IsTrue(await response.Content.ReadAsAsync<int>() == result);
        }
    }
    

这是一个集成测试,而不是单元测试。如果你想自动化这个,你必须有一个工具来启动/托管你的web api,然后执行请求。

如果你想把它作为一个单元测试,你可以验证类和方法的属性,并检查值。

var type = typeof(Controller);
var attributeRoutePrefix = type.GetCustomAttribute(typeof(RoutePrefixAttribute)) as RoutePrefixAttribute;
Assert.IsNotNull(attributeRoutePrefix);
Assert.AreEqual("prefix", attributeRoutePrefix.Prefix);
var methodAttribute = type.GetMethod(nameof(Controller.Add)).GetCustomAttribute(typeof(RouteAttribute)) as RouteAttribute;
Assert.IsNotNull(methodAttribute);
Assert.AreEqual("id1", methodAttribute.Template);

可以使用postman或fiddler来测试url参数。