Owin托管webapi 2.2.用模拟服务测试控制器

本文关键字:服务 测试 控制器 模拟 托管 webapi Owin | 更新日期: 2023-09-27 18:05:47

我有webapi,用于测试目的,我在自己的托管。我已经用自动设置了。现在当我在测试时,我想注入最少的依赖项。到目前为止我还不能。我已经阅读了文档,并做了一些研究,但我错过了一些东西。

是测试代码。

 [Test]
    public void Request_all_airports()
    {
        const int port = 8086;
        AirportCollection moqAirportCollection = new AirportCollection();
        moqAirportCollection.Airports = new List<Airport>{new Airport{IATA = "moq",Name = "moqName"}};
        using (WebApp.Start<Startup>("http://localhost:" + port))
        {
            using (var mock = AutoMock.GetLoose())
            {
                var moqObj =  mock.Mock<IAirportService>().Setup(x => x.GetAirports()).Returns(moqAirportCollection);
                var client = new HttpClient {BaseAddress = new Uri("http://localhost:" + port)};
                var response = client.GetAsync("/api/airport/get").Result;
                var body = response.Content.ReadAsStringAsync().Result;
                var airportCollection = JsonConvert.DeserializeObject<AirportCollection>(body);
            }
        }
    }

请看一看。让我知道我错过了什么。如果你想看控制器代码或任何其他部分,请告诉我。

下面是启动代码

 public class Startup
{
    public static IContainer container { get; set; }
    public void Configuration(IAppBuilder appBuilder)
    {
        var httpConfig = new HttpConfiguration();
        container = AutofacSetup.Register(httpConfig);
        WebApiConfig.Register(httpConfig);

        appBuilder.UseAutofacMiddleware(container);
        appBuilder.UseAutofacWebApi(httpConfig);
        appBuilder.UseWebApi(httpConfig);
    }
}

感谢

我想我已经在别人的帮助下解决了它。这是我的代码。

var moq = new Mock<IAirportService>();
                moq.Setup(x => x.GetAirports()).Returns(moqAirportCollection);
                newBuilder.RegisterInstance(moq.Object).As<IAirportService>();
                newBuilder.Update(Startup.container);

我没有重新构建包含,我只是更新了它。autofacc有使用最新注册的行为,所以它会在这里使用mock。

Owin托管webapi 2.2.用模拟服务测试控制器

你就快成功了。

在您的测试中,您需要向您的 autofacc 容器注册您的模拟服务,以便通过应用程序中的模拟解析对IAirportService的依赖。实现这一目标的一种方法是为每个测试覆盖Startup类的Configuration方法,并将测试DI放在那里。我在下面写了一些注释来说明可以做的修改:
public class Startup
{
    public static IContainer container { get; set; }
    // make this virtual
    public virtual void Configuration(IAppBuilder appBuilder)
    {
        var httpConfig = new HttpConfiguration();
        // have this return the ContainerBuilder instead of the container
        var builder = AutofacSetup.Register(httpConfig)
        container = builder.Build();
        WebApiConfig.Register(httpConfig);

        appBuilder.UseAutofacMiddleware(container);
        appBuilder.UseAutofacWebApi(httpConfig);
        appBuilder.UseWebApi(httpConfig);
    }
}

然后在您的测试类中,从Startup类派生并放入您的测试逻辑。像这样:

public class MyTestCase {
        public static Mock<IAirportService> MockObj { get; set; }
        private class TestStartup : Startup {
            public override void Configuration(IAppBuilder app) {
                var httpConfig = new HttpConfiguration();
                // this now returns ContainerBuilder instead of the container
                var builder = AutofacSetup.Register(httpConfig)
                // register your mock, change this to whatever lifetime scope you need
                var moqAirportCollection = new AirportCollection();
                moqAirportCollection.Airports = new List<Airport>{new Airport{IATA = "moq",Name = "moqName"}};
                var mock = AutoMock.GetLoose()
                MockObj = mock.Mock<IAirportService>()
                                           .Setup(x => x.GetAirports())
                                           .Returns(moqAirportCollection);
                var moqObj = MockObj.Object;
                builder.RegisterInstance(moqObj).As<IAirportService>();

                container = builder.Build();
                WebApiConfig.Register(httpConfig);

                appBuilder.UseAutofacMiddleware(container);
                appBuilder.UseAutofacWebApi(httpConfig);
                appBuilder.UseWebApi(httpConfig);
            }
        }
        [Test]
        public void Request_all_airports()
        {    
           using (var server = WebApp.Start<Startup>())
           {
               var response = 
                   server.CreateRequest("/api/airport/get")
                         .GetAsync()
                         .Result;
                var body = response.Content.ReadAsStringAsync().Result;
                var result = JsonConvert.DeserializeObject<AirportCollection>(body);
                // assert something
            }
        }
    }

单元测试应该测试单个组件。在您的示例中,您试图通过HTTP查询测试AirportController,而不是将AirportController作为独立组件。

AirportController类依赖于IAirportService组件。为了测试没有任何依赖的组件,您在IAirportService上创建了一个moq。现在您可以用这个moq实例化一个新的AirportController,并使用这个实例运行您的测试。

如果你有一个像这样的AirportController

public class AirportController
{
    public AirportController(IAirportService airportService) { /* ... */}
}

AirportController测试应该是这样的:

[Test]
public void Request_all_airports()
{
    AirportCollection moqAirportCollection = new AirportCollection();
    var moqAirPort = new Airport{ IATA = "moq",Name = "moqName" };
    moqAirportCollection.Airports = new List<Airport>{ moqAirPort };
    using (var mock = AutoMock.GetLoose())
    {
        var moqAirportService = mock.Mock<IAirportService>()
                                    .Setup(x => x.GetAirports())
                                    .Returns(moqAirportCollection);
        var testedAirportController = new AirportController(moqAirportService); 
        AirportCollection airportCollection = testedAirportController.Get();
        Assert.AreEquals(1, airportCollection.Length, "Invalid number of airport"); 
        Assert.AreEquals(moqAirPort.Name, airportCollection[0].Name, "Invalid name");
    }
}