C# Owin托管的webapi 2.2。用模拟服务测试控制器
我有webapi,出于测试目的,我在owin中托管它。我已经用autofac设置好了。现在,当我进行测试时,我想注入moq依赖项。到目前为止,我还不能做到这一点。我已经阅读了文档并做了一些研究,但我遗漏了一些东西 下面是测试代码C# Owin托管的webapi 2.2。用模拟服务测试控制器,c#,unit-testing,asp.net-web-api,owin,autofac,C#,Unit Testing,Asp.net Web Api,Owin,Autofac,我有webapi,出于测试目的,我在owin中托管它。我已经用autofac设置好了。现在,当我进行测试时,我想注入moq依赖项。到目前为止,我还不能做到这一点。我已经阅读了文档并做了一些研究,但我遗漏了一些东西 下面是测试代码 [Test] public void Request_all_airports() { const int port = 8086; AirportCollection moqAirportCollection = ne
[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);
}
}
}
谢谢
我想是的,我在人们的帮助下解决了这个问题。这是我的密码
var moq = new Mock<IAirportService>();
moq.Setup(x => x.GetAirports()).Returns(moqAirportCollection);
newBuilder.RegisterInstance(moq.Object).As<IAirportService>();
newBuilder.Update(Startup.container);
var moq=new Mock();
moq.Setup(x=>x.GetAirports()).Returns(moqAirportCollection);
RegisterInstance(moq.Object.As();
newBuilder.Update(Startup.container);
我没有重建控件,我只是更新了它。autofac有使用最新注册的行为,因此它将在此处使用Mock on 单元测试应该测试单个组件。在本例中,您试图通过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");
}
}
[测试]
公共作废申请(所有)机场()
{
AirportCollection moqAirportCollection=新建AirportCollection();
var moqAirPort=新机场{IATA=“moq”,Name=“moqName”};
moqAirportCollection.Airports=新列表{moqAirPort};
使用(var mock=AutoMock.GetLoose())
{
var moqAirportService=mock.mock()
.Setup(x=>x.GetAirports())
.退货(moqAirportCollection);
var testedAirportController=新机场控制器(moqAirportService);
AirportCollection AirportCollection=testedAirportController.Get();
arequals(1,airportCollection.Length,“无效的机场号”);
Assert.AreEquals(moqAirPort.Name,airportCollection[0].Name,“无效名称”);
}
}
单元测试应该测试单个组件。在本例中,您试图通过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");
}
}
[测试]
公共作废申请(所有)机场()
{
AirportCollection moqAirportCollection=新建AirportCollection();
var moqAirPort=新机场{IATA=“moq”,Name=“moqName”};
moqAirportCollection.Airports=新列表{moqAirPort};
使用(var mock=AutoMock.GetLoose())
{
var moqAirportService=mock.mock()
.Setup(x=>x.GetAirports())
.退货(moqAirportCollection);
var testedAirportController=新机场控制器(moqAirportService);
AirportCollection AirportCollection=testedAirportController.Get();
arequals(1,airportCollection.Length,“无效的机场号”);
Assert.AreEquals(moqAirPort.Name,airportCollection[0].Name,“无效名称”);
}
}
你就快到了
在测试中,您需要向autofac容器注册模拟服务,以便通过应用程序中的模拟解决对IAirportService
的依赖关系
实现这一点的一种方法是覆盖每个测试的启动
class'配置
方法,并将测试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
}
}
}
公共类MyTestCase{
公共静态模拟MockObj{get;set;}
私有类TestStartup:Startup{
公共覆盖无效配置(IAppBuilder应用程序){
var httpConfig=new HttpConfiguration();
//现在将返回ContainerBuilder而不是容器
var builder=AutofacSetup.Register(httpConfig)
//注册您的模拟,将其更改为您需要的任何生存期范围
var moqAirportCollection=new AirportCollection();
moqAirportCollection.Airports=新列表{新机场{IATA=“moq”,Name=“moqName”};
var mock=AutoMock.GetLoose()
MockObj=mock.mock()
.Setup(x=>x.GetAirports())
.退货(moqAirportCollection);
var moqObj=MockObj.Object;
builder.RegisterInstance(moqObj.As();
container=builder.Build();
WebApiConfig.Register(httpConfig);
appBuilder.useAutofacidleware(容器);
appBuilder.UseAutofacWebApi(httpConfig);
appBuilder.UseWebApi(httpConfig);
}
}
[测试]
公共作废申请(所有)机场()
{
使用(var server=WebApp.Start())
{
var响应=
CreateRequest(“/api/airport/get”)
.GetAsync()
后果
var body=response.Content.ReadAsStringAsync().Result;
弗吉尼亚州