在 Web 服务上进行集成测试的问题在于,它并不能告诉您很多关于问题的信息 - 或者即使确实存在问题,如果存在,它也不会告诉您问题出在哪里谎言。它要么成功,要么失败。所以在这方面你得到了 200 响应代码还是 500 响应代码......但它失败了,因为:
- 服务器无法访问
- Web 服务未启动,或尝试启动时失败
- 防火墙阻止了网络
- 未找到数据库记录
- 存在数据库架构问题,实体框架未启动
正确。
它实际上可以是任何东西——你的开发机器上的结果可能不同于生产机器上的结果——那么它真正告诉你关于你的应用程序的什么?
强大的软件的关键在于测试您的产品是否能够正确、优雅和稳健地处理任何这些情况。
我这样写我的控制器动作:
public HttpResponseMessage Get(int id)
{
try
{
var person = _personRepository.GetById(id);
var dto = Mapper.Map<PersonDto>(person);
HttpResponseMessage response = Request.CreateResponse<PersonDto>(HttpStatusCode.OK, dto);
return response;
}
catch (TextFileDataSourceException ex)
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.InternalServerError);
return response;
}
catch (DataResourceNotFoundException ex)
{
HttpResponseMessage response = Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
return response;
}
catch (FormatException ex)
{
HttpResponseMessage response = Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
return response;
}
catch (Exception ex)
{
HttpResponseMessage response = Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
return response;
}
}
try 块获取数据,创建 dto 并返回带有 200 代码的数据。这里处理了几个错误情况,但没有一个表明我的 Web 服务本身有问题,有些(404 错误)甚至不表明应用程序有问题 - 如果我的应用程序找不到,我预计会出现 NotFoundException 和 404记录 - 如果发生这种情况,我的应用程序在这种情况下工作。
因此,如果出现任何这些错误情况,并不是因为 Web 服务有问题,也不一定是应用程序有问题。但我可以测试我的 Web 服务是否会针对任何这些预期条件返回正确的响应。
此控制器操作的测试如下所示:
[Test]
public void CanGetPerson()
{
#region Arrange
var person = new Person
{
Id = 1,
FamilyName = "Rooney",
GivenName = "Wayne",
MiddleNames = "Mark",
DateOfBirth = new DateTime(1985, 10, 24),
DateOfDeath = null,
PlaceOfBirth = "Liverpool",
Height = 1.76m,
TwitterId = "@WayneRooney"
};
Mapper.CreateMap<Person, PersonDto>();
var mockPersonRepository = new Mock<IPersonRepository>();
mockPersonRepository.Setup(x => x.GetById(1)).Returns(person);
var controller = new PersonController(mockPersonRepository.Object);
controller.Request = new HttpRequestMessage(HttpMethod.Get, "1");
controller.Configuration = new HttpConfiguration(new HttpRouteCollection());
#endregion
#region act
HttpResponseMessage result = controller.Get(1);
#endregion
#region assert
Assert.AreEqual(HttpStatusCode.OK, result.StatusCode);
#endregion
}
[Test]
public void CanHandlePersonNotExists()
{
#region Arrange
var mockPersonRepository = new Mock<IPersonRepository>();
mockPersonRepository.Setup(x => x.GetById(1)).Throws<DataResourceNotFoundException>();
var controller = new PersonController(mockPersonRepository.Object)
{
Request = new HttpRequestMessage(HttpMethod.Get, "1"),
Configuration = new HttpConfiguration(new HttpRouteCollection())
};
#endregion
#region Act
HttpResponseMessage result = controller.Get(1);
#endregion
#region Assert
Assert.AreEqual(HttpStatusCode.NotFound, result.StatusCode);
#endregion
}
[Test]
public void CanHandleServerError()
{
#region Arrange
var mockPersonRepository = new Mock<IPersonRepository>();
mockPersonRepository.Setup(x => x.GetById(1)).Throws<Exception>();
var controller = new PersonController(mockPersonRepository.Object);
controller.Request = new HttpRequestMessage(HttpMethod.Get, "1");
controller.Configuration = new HttpConfiguration(new HttpRouteCollection());
#endregion
#region Act
HttpResponseMessage result = controller.Get(1);
#endregion
#region Assert
Assert.AreEqual(HttpStatusCode.InternalServerError, result.StatusCode);
#endregion
}
请注意,我正在引入一个模拟存储库,并让我的模拟存储库触发 404 和服务器错误的预期异常,并确保 Web 服务正确处理它。
这告诉我的是,我的 Web 服务应该处理预期和异常情况并返回适当的代码:200/404/500。
虽然有些是错误状态,有些是成功状态,但这些结果都没有表明我的 Web 服务有问题 - 它的行为完全符合其应有的状态,这正是我想要测试的。
对 Web 服务的“跨网络”集成测试无法告诉您应用程序的稳健性或正确性 - 或者即使它返回正确的数据或响应代码。
不要尝试重新测试 WebAPI...Microsoft 已经为它编写了大量的测试套件 - 数百个测试夹具类,数千个测试方法:
https://aspnetwebstack.codeplex.com/SourceControl/latest#test/System.Web.Http.Test/Controllers/ApiControllerTest.cs
假设 WebAPI 可以正常工作,并且不需要您再次对其进行测试。专注于测试您的应用程序代码并确保您的 Web 服务能够优雅地处理成功和错误条件。
如果您想检查您的网络服务是否已连接并在网络上可用 - 打开浏览器并手动测试;无需自动化;结果会因环境和外部条件而异。
以相同的方式测试应用程序的每一层,模拟上一层并测试当前层处理上一层的所有可能结果。
您的服务的客户端应用程序应该做同样的事情:模拟 Web 服务,并假装它给出了 404 - 并检查它是否按应有的方式处理。