C# 使用Web API SelfHost进行Specflow测试

C# 使用Web API SelfHost进行Specflow测试,c#,testing,asp.net-web-api,self-hosting,C#,Testing,Asp.net Web Api,Self Hosting,我有一个服务项目(WebAPI)和一个可以访问服务api的客户端项目。我想使用Specflow(或类似的东西)进行端到端测试。我希望通过测试控制服务的配置方式,以便在需要时使用mock/stubs/dummie 当WCF是最酷的东西时,我做了这样的测试,通过创建我的服务实例并使用标准的.NETServiceHost托管它们。所有这些都是通过编程实现的。它就像一个符咒。我想用我的WebAPI服务做一些类似的事情,所以我认为自托管是一种方式。但由于某种原因,这真的很难开始工作(比如,我还没有成功)

我有一个服务项目(WebAPI)和一个可以访问服务api的客户端项目。我想使用Specflow(或类似的东西)进行端到端测试。我希望通过测试控制服务的配置方式,以便在需要时使用mock/stubs/dummie

当WCF是最酷的东西时,我做了这样的测试,通过创建我的服务实例并使用标准的.NETServiceHost托管它们。所有这些都是通过编程实现的。它就像一个符咒。我想用我的WebAPI服务做一些类似的事情,所以我认为自托管是一种方式。但由于某种原因,这真的很难开始工作(比如,我还没有成功)

有人做过类似的事情吗?我不想让Nance参与进来,除非这是唯一的办法

我需要的是: 1.以编程方式启动服务,以控制服务的配置方式(注入哪些依赖项等) 2.调用客户端api上的方法(或者实际上只是在测试中执行WebRequests)来访问我刚刚启动的服务。 3.性能并不是一个真正的问题,但代码的清晰性才是关键

有人吗

最终解决方案:

我的问题实际上与自我托管无关。我的Get方法有一个带有自定义路由的参数:

    [Route("api/PermissionChoice/{customerId}")]
    public IEnumerable<PermissionChoice> Get(Guid customerId)
[路由(“api/PermissionChoice/{customerId}”)]
公共IEnumerable Get(Guid customerId)
但在启动selfhost时,不应用自定义路由。需要考虑自定义路由的配置

最终结果如下所示:

    [Fact]
    public void WhatDoesItTest()
    {
        using (WebApp.Start<Startup>(_baseAddress))
        {
            var client = new HttpClient();
            var response = client.GetAsync(_baseAddress + "api/PermissionChoice/4351A155-3F4B-46CE-9C7A-4BA377D5FDDF").Result;
            var permissionChoices = response.Content.ReadAsAsync<IEnumerable<PermissionChoice>>().Result;
            permissionChoices.First().PermissionId.Should().NotBeEmpty();
        }
    }

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var config = new HttpConfiguration();
            config.Routes.MapHttpRoute(
                name: "Default",
                routeTemplate: "api/{controller}/{customerId}",
                defaults: new {customerId = RouteParameter.Optional});

            var container = new WindsorContainer();
            container.Install(FromAssembly.This());
            config.DependencyResolver = new WindsorDependencyResolver(container);

            app.UseWebApi(config);
        }
    }
[事实]
公共无效WhatDesittest()
{
使用(WebApp.Start(_baseAddress))
{
var client=新的HttpClient();
var response=client.GetAsync(_baseAddress+“api/PermissionChoice/4351155-3F4B-46CE-9C7A-4BA377D5FDDF”)。结果;
var permissionChoices=response.Content.ReadAsAsync().Result;
permissionChoices.First().PermissionId.Should().NotBeEmpty();
}
}
公营创业
{
公共无效配置(IAppBuilder应用程序)
{
var config=新的HttpConfiguration();
config.Routes.MapHttpRoute(
名称:“默认”,
routeTemplate:“api/{controller}/{customerId}”,
默认值:new{customerId=RouteParameter.Optional});
var container=新的WindsorContainer();
container.Install(fromsassembly.This());
config.DependencyResolver=新的WindsorDependencyResolver(容器);
app.UseWebApi(配置);
}
}

您可以创建一个自主机和主机控制器,并根据控制器设置模拟依赖项

public static class HttpClientFactory
{
    private static HttpClient httpClient;

    public static HttpClient Create()
    {
        if (httpClient == null)
        {
            var baseAddress = new Uri("http://localhost:8081");
            var configuration = new HttpSelfHostConfiguration(baseAddress);
            var selfHostServer = new HttpSelfHostServer(configuration);

            httpClient = new HttpClient(selfHostServer) {BaseAddress = baseAddress};

            return httpClient;
        }
        return httpClient;
    }
}
}

此主机在自主机环境中托管Web Api,您可以模拟依赖关系

这是否需要specflow标记?这真的是specflow特有的吗?@SamHolder你说得对。我已经移除了specflow标签。谢谢。虽然我最终使用了WebApp.Start(_baseAddress)解决方案,但您的帖子在一定程度上帮助我找到了正确的方法。