ASP.NET 测试 Api 控制器:Uri(Request.GetEncodedUrl()...) returns null
ASP.NET Testing Api controller: Uri(Request.GetEncodedUrl()...) returns null
我正在测试一个 ASP.NET 核心 Api post 方法,但是我得到一个 System.NullReferenceException 导致我的测试失败。
当我尝试 return a Created()-ActionResult 时出现 null 异常,如下所示:
return Created(new Uri(Request.GetEncodedUrl() + "/" + personDto.Id), personDto);
我的 personDto.Id 和 personDto 都不为空,但是 Uri() return 的结果为空。我用谷歌搜索但没有找到解决方案,但我相信我必须以某种方式模拟 Uri() 方法(我是测试新手,一般来说 asp.net)。 Api 在 "live" 针对 SQL 服务器进行测试时运行良好。
我正在使用 Moq 和 NUnit 进行测试,下面是我的设置和测试方法的一部分:
public void SetUp()
{
_mapper = GenerateConcreteInstance();
_personService = new Mock<IPersonService>();
_personService.Setup(ps => ps.Create(It.IsAny<Person>())).Verifiable();
_controller = new PeopleController(_personService.Object, _mapper);
}
[Test]
public void CreatePerson_WhenCalled_IsNotNull()
{
var personDto = new PersonDto()
{
Id = 3,
Firstname = "Karl",
Lastname = "Karlsson",
City = "Oslo",
Email = "karl.karlsson@test.com"
};
var result = _controller.CreatePerson(personDto);
var createdResult = result as CreatedResult;
Assert.IsNotNull(createdResult);
}
我正在尝试测试的控制器:
[HttpPost]
public IActionResult CreatePerson(PersonDto personDto)
{
if (!ModelState.IsValid)
return BadRequest();
var person = _mapper.Map<PersonDto, Person>(personDto);
person.DateCreated = DateTime.Now;
_personService.Create(person);
_personService.Save();
personDto.Id = person.Id;
return Created(new Uri(Request.GetEncodedUrl() + "/" + personDto.Id), personDto);
}
如何正确设置此测试以避免空异常?如果我的测试在任何其他方面都不好,将不胜感激有关如何解决此问题的任何帮助和一般指示。
更新
我把测试修改成这样了。我在正确的轨道上吗?
public void CreatePerson_WhenCalled_IsNotNull()
{
var personDto = new PersonDto()
{
Id = 3,
Firstname = "Karl",
Lastname = "Karlsson",
City = "Oslo",
Email = "karl.karlsson@test.com"
};
var request = new Mock<HttpRequest>();
request.Setup(x => x.Headers).Returns(
new HeaderDictionary {
{"X-Requested-With", "XMLHttpRequest"}
});
var context = new Mock<HttpContext>();
context.Setup(x => x.Request).Returns(request.Object);
_controller.ControllerContext = new ControllerContext()
{
HttpContext = context.Object
};
var result = _controller.CreatePerson(personDto);
var createdResult = result as CreatedResult;
Assert.IsNotNull(createdResult);
}
Request.GetEncodedUrl()
扩展依赖于有效请求。
/// <summary>
/// Returns the combined components of the request URL in a fully escaped form suitable for use in HTTP headers
/// and other HTTP operations.
/// </summary>
/// <param name="request">The request to assemble the uri pieces from.</param>
/// <returns>The encoded string version of the URL from <paramref name="request"/>.</returns>
public static string GetEncodedUrl(this HttpRequest request)
{
return BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path, request.QueryString);
}
哪个会失败
if (scheme == null)
{
throw new ArgumentNullException(nameof(scheme));
}
没有与显示的示例关联的上下文或请求,因此我建议提供一个有效的上下文,其中填充了必要的成员,以便按预期执行测试。
//...omitted for brevity
var httpContext = new DefaultHttpContext();
//http://localhost/example
httpContext.Request.Scheme = "http";
httpContext.Request.Host = new HostString("localhost");
//Controller needs a controller context
var controllerContext = new ControllerContext() {
HttpContext = httpContext,
};
//assign context to controller
_controller.ControllerContext = controllerContext;
//...omitted for brevity
我正在测试一个 ASP.NET 核心 Api post 方法,但是我得到一个 System.NullReferenceException 导致我的测试失败。
当我尝试 return a Created()-ActionResult 时出现 null 异常,如下所示:
return Created(new Uri(Request.GetEncodedUrl() + "/" + personDto.Id), personDto);
我的 personDto.Id 和 personDto 都不为空,但是 Uri() return 的结果为空。我用谷歌搜索但没有找到解决方案,但我相信我必须以某种方式模拟 Uri() 方法(我是测试新手,一般来说 asp.net)。 Api 在 "live" 针对 SQL 服务器进行测试时运行良好。
我正在使用 Moq 和 NUnit 进行测试,下面是我的设置和测试方法的一部分:
public void SetUp()
{
_mapper = GenerateConcreteInstance();
_personService = new Mock<IPersonService>();
_personService.Setup(ps => ps.Create(It.IsAny<Person>())).Verifiable();
_controller = new PeopleController(_personService.Object, _mapper);
}
[Test]
public void CreatePerson_WhenCalled_IsNotNull()
{
var personDto = new PersonDto()
{
Id = 3,
Firstname = "Karl",
Lastname = "Karlsson",
City = "Oslo",
Email = "karl.karlsson@test.com"
};
var result = _controller.CreatePerson(personDto);
var createdResult = result as CreatedResult;
Assert.IsNotNull(createdResult);
}
我正在尝试测试的控制器:
[HttpPost]
public IActionResult CreatePerson(PersonDto personDto)
{
if (!ModelState.IsValid)
return BadRequest();
var person = _mapper.Map<PersonDto, Person>(personDto);
person.DateCreated = DateTime.Now;
_personService.Create(person);
_personService.Save();
personDto.Id = person.Id;
return Created(new Uri(Request.GetEncodedUrl() + "/" + personDto.Id), personDto);
}
如何正确设置此测试以避免空异常?如果我的测试在任何其他方面都不好,将不胜感激有关如何解决此问题的任何帮助和一般指示。
更新
我把测试修改成这样了。我在正确的轨道上吗?
public void CreatePerson_WhenCalled_IsNotNull()
{
var personDto = new PersonDto()
{
Id = 3,
Firstname = "Karl",
Lastname = "Karlsson",
City = "Oslo",
Email = "karl.karlsson@test.com"
};
var request = new Mock<HttpRequest>();
request.Setup(x => x.Headers).Returns(
new HeaderDictionary {
{"X-Requested-With", "XMLHttpRequest"}
});
var context = new Mock<HttpContext>();
context.Setup(x => x.Request).Returns(request.Object);
_controller.ControllerContext = new ControllerContext()
{
HttpContext = context.Object
};
var result = _controller.CreatePerson(personDto);
var createdResult = result as CreatedResult;
Assert.IsNotNull(createdResult);
}
Request.GetEncodedUrl()
扩展依赖于有效请求。
/// <summary>
/// Returns the combined components of the request URL in a fully escaped form suitable for use in HTTP headers
/// and other HTTP operations.
/// </summary>
/// <param name="request">The request to assemble the uri pieces from.</param>
/// <returns>The encoded string version of the URL from <paramref name="request"/>.</returns>
public static string GetEncodedUrl(this HttpRequest request)
{
return BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path, request.QueryString);
}
哪个会失败
if (scheme == null)
{
throw new ArgumentNullException(nameof(scheme));
}
没有与显示的示例关联的上下文或请求,因此我建议提供一个有效的上下文,其中填充了必要的成员,以便按预期执行测试。
//...omitted for brevity
var httpContext = new DefaultHttpContext();
//http://localhost/example
httpContext.Request.Scheme = "http";
httpContext.Request.Host = new HostString("localhost");
//Controller needs a controller context
var controllerContext = new ControllerContext() {
HttpContext = httpContext,
};
//assign context to controller
_controller.ControllerContext = controllerContext;
//...omitted for brevity