[英]How to get the Values from a Task<IActionResult> returned through an API for Unit Testing
我使用 ASP.NET MVC Core v2.1 創建了一個 API。 我的HttpGet
方法之一設置如下:
public async Task<IActionResult> GetConfiguration([FromRoute] int? id)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
..... // Some code here
return Ok(configuration);
}
catch (Exception ex)
{
... // Some code here
}
}
在進行單元測試時,我可以檢查 Ok 是響應,但我確實需要查看配置的值。 我似乎無法讓它與以下一起工作:
[TestMethod]
public void ConfigurationSearchGetTest()
{
var context = GetContextWithData();
var controller = new ConfigurationSearchController(context);
var items = context.Configurations.Count();
var actionResult = controller.GetConfiguration(12);
Assert.IsTrue(true);
context.Dispose();
}
在運行時,我可以檢查actionResult
是否具有某些我無法編碼的值。 有什么我做錯了嗎? 還是我只是在想這個錯誤? 我希望能夠做到:
Assert.AreEqual(12, actionResult.Values.ConfigurationId);
您可以在不更改返回類型的情況下獲得經過測試的控制器。
IActionResult
是所有其他人的基本類型。
將結果轉換為預期類型並將返回值與預期進行比較。
由於您正在測試異步方法,因此也要使測試方法異步。
[TestMethod]
public async Task ConfigurationSearchGetTest()
{
using (var context = GetContextWithData())
{
var controller = new ConfigurationSearchController(context);
var items = context.Configurations.Count();
var actionResult = await controller.GetConfiguration(12);
var okResult = actionResult as OkObjectResult;
var actualConfiguration = okResult.Value as Configuration;
// Now you can compare with expected values
actualConfuguration.Should().BeEquivalentTo(expected);
}
}
好的做法是建議您在控制器操作中沒有大量代碼需要測試,並且大部分邏輯位於其他更容易測試的解耦對象中。 話雖如此,如果您仍然想測試您的控制器,那么您需要使您的測試async
並等待調用。
您將遇到的問題之一是您正在使用IActionResult
因為它允許您返回BadRequest(...)
和Ok(...)
。 但是,由於您使用的是 ASP.NET MVC Core 2.1,您可能希望開始使用新的ActionResult<T>
類型。 這應該有助於您的測試,因為您現在可以直接訪問強類型返回值。 例如:
//Assuming your return type is `Configuration`
public async Task<ActionResult<Configuration>> GetConfiguration([FromRoute] int? id)
{
try
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
..... // Some code here
// Note we are now returning the object directly, there is an implicit conversion
// done for you
return configuration;
}
catch (Exception ex)
{
... // Some code here
}
}
請注意,我們現在直接返回對象,因為存在從Foo
到ActionResult<Foo>
的隱式轉換
現在你的測試看起來像這樣:
[TestMethod]
public async Task ConfigurationSearchGetTest()
{
var context = GetContextWithData();
var controller = new ConfigurationSearchController(context);
var items = context.Configurations.Count();
// We now await the call
var actionResult = await controller.GetConfiguration(12);
// And the value we want is now a property of the return
var configuration = actionResult.Value;
Assert.IsTrue(true);
context.Dispose();
}
由於我的聲譽不允許我評論 @DavidG 的答案是正確的,我將放一個關於如何在Task<IActionResult>
獲取值的示例。
正如@ Christopher J. Reynolds 指出的那樣, actionResult.Value
可以在運行時看到,但不能在編譯時看到。
因此,我將展示一個獲取Values
的基本測試:
[TestMethod]
public async Task Get_ReturnsAnArea()
{
// Arrange
string areaId = "SomeArea";
Area expectedArea = new Area() { ObjectId = areaId, AreaNameEn = "TestArea" };
var restClient = new Mock<IRestClient>();
restClient.Setup(client => client.GetAsync<Area>(It.IsAny<string>(), false)).ReturnsAsync(expectedArea);
var controller = new AreasController(restClient.Object);
//// Act
// We now await the call
IActionResult actionResult = await controller.Get(areaId);
// We cast it to the expected response type
OkObjectResult okResult = actionResult as OkObjectResult;
// Assert
Assert.IsNotNull(okResult);
Assert.AreEqual(200, okResult.StatusCode);
Assert.AreEqual(expectedArea, okResult.Value);
// We cast Value to the expected type
Area actualArea = okResult.Value as Area;
Assert.IsTrue(expectedArea.AreaNameEn.Equals(actualArea.AreaNameEn));
}
當然,這可以改進,但我只是想向您展示一個簡單的方法來獲得它。
我希望它有幫助。
您需要等待對 GetConfiguration 的調用以獲取 IActionResult 對象,如下所示:
var actionResult = await controller.GetConfiguration(12);
為此,您還需要將測試方法的簽名更改為異步。 所以改變這個:
public void ConfigurationSearchGetTest()
對此:
public async Task ConfigurationSearchGetTest()
如果您需要快速解決方案,請使用 JsonConvert.SerializeObject() ,然后使用 JsonConvert.DeserializeObject() 然后您將獲得帶有值的對象。
[TestMethod]
public async Task ConfigurationSearchGetTest()
{
using (var context = GetContextWithData())
{
var controller = new ConfigurationSearchController(context);
var items = context.Configurations.Count();
var actionResult = await controller.GetConfiguration(12);
var okResult = actionResult as OkObjectResult;
var actualConfiguration = okResult.Value ;
//
//IMPORTANT ONLY BELOW two lines need.
//
var actualConfigurationJStr=JsonConvert.SerializeObject( okResult.Value );
var hereObjectWithStrongType=JsonConvert.DeserializeObject<Configuration>(actualConfigurationJStr);
// Now you can compare with expected values
actualConfuguration.Should().BeEquivalentTo(expected);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.