我是 unittest 的新手,也很困惑我希望你能幫助我理解幾件事,我想為以下場景撰寫一個 Xunit 測驗:
我有以下控制器:
[ApiController]
[Route("api/[controller]")]
public class HomeController : ControllerBase
{
public readonly IDataService _dataService;
public HomeController(IDataService dataservice)
{
_dataService = dataservice;
}
[HttpGet("/value")]
public IActionResult GetTotal(string name, string year)
{
var totalAmount = _dataService.GetToTalValue(name, year);
return Ok(totalAmount.Result);
}
我有存盤庫類可以與資料庫交談,我將其命名為資料服務:
public interface IDataService
{
public Task<decimal> GetTotal(string name, string year)
}
實作很簡單,我只是寫下我回傳的內容來制作長篇故事:
public Task<decimal> GetTotal(string name, string year){
///here i connect to db and get data and return to controller
return Task.FromResult(totalAmount);
}
最后,我按照一些在線教程創建了一個單元測驗:
public class UnitTest1
{
[Fact]
public void Test1()
{
var sut = new Mock<IDataService>();
sut.Setup(s => s.GetTotal("ASK", "1235")).ReturnsAsync(1231);
HomeController mm = new HomeController(sut.Object);
var result = mm.GetTotal("ASK", "1235");
///asset gives error because cant convert iactionresult to decimal
}
}
}
首先我不明白為什么我們需要寫:
sut.Setup(s => s.GetTotal("ASK", "1235")).ReturnsAsync(1231);
因為我們將再次使用控制器進行確切的處理:
HomeController mm = new HomeController(sut.Object);
var result = mm.GetTotal("ASK", "1235");
該設定意味著我將兩個值傳遞給 GetTotal 并期望 1231 對嗎?那么測驗控制器的意義何在?請幫助我理解它,我的第二個問題是我從 iactionresult 得到的結果是十進制但在斷言中我得到錯誤,我無法將 iactionresult 轉換為十進制
任何幫助將不勝感激
uj5u.com熱心網友回復:
鑒于服務被定義為異步,該操作也應該是異步的
[HttpGet("/value")]
public async Task<IActionResult> GetTotal(string name, string year) {
decimal totalAmount = await _dataService.GetToTalValue(name, year);
return Ok(totalAmount);
}
否則保持一切同步
對于單元測驗,您正在單獨驗證被測物件的預期行為。
同樣,由于主題是異步的,那么測驗也應該是異步的
public class UnitTest1 {
[Fact]
public async Task Test1() {
//Arrange
string name = "ASK";
string year = "1235";
decimal expected = 1231M;
//setup expectations of the mocked dependency
var mock = new Mock<IDataService>();
mock.Setup(_ => _.GetTotalValue(name, year)).ReturnsAsync(expected);
HomeController sut = new HomeController(mock.Object);
//Act
IActionResult result = await sut.GetTotal(name, year);
//Need to convert to actual action result Type
OkObjectResult okResult = result as OkObjectResult;
//Assert
okResult.Should().NotBeNull(); //using FluentAssertions
//need to extract the actual value within the result
decimal actual = (decimal)okResult.Value;
//verify expected behavior
actual.Should().Be(expected); //using FluentAssertions
}
}
由于給出的示例的簡單性質,這??已經被簡化,但這里的最終目標是通過給它已知值和斷言預期結果來驗證被測物件的預期行為。
由于在這種情況下被測物件是控制器,因此IDataService對于此隔離測驗的目的,實際介面的實作無關緊要。模擬所需的行為并將模擬的依賴項賦予控制器(主體)。
uj5u.com熱心網友回復:
如果你模擬一個介面,你沒有測驗介面中方法的結果,你認為資料服務正在作業并強制結果。這應該是
sut.Setup(s => s.GetToTalValue("ASK", "1235")).ReturnsAsync(10);
您必須圍繞此介面測驗其他邏輯。例如,如果控制器正確傳遞引數并回傳正確值
[Fact]
public void Test1()
{
decimal resultTotal = 10;
string name = "ASK";
string year = "1235";
var mockDataService = new Mock<IDataService>();
mockDataService.Setup(s => s.GetToTalValue(name, year)).ReturnsAsync(resultTotal);
HomeController sut = new HomeController(mockDataService.Object);
IActionResult result = sut.GetTotal(name, year);
Assert.True(result is OkObjectResult);
Assert.True((decimal)((result as OkObjectResult)?.Value) == resultTotal);
}
uj5u.com熱心網友回復:
第一個問題很自以為是,這是一個非常簡單的Action,我只是為了“測驗”而撰寫測驗和一些回歸測驗,如果添加更多邏輯,我肯定會為更改撰寫測驗。
第二個問題,OK()是OkObjectResult的便捷方法,因此您可以將其轉換為:
var result = (OkObjectResult) mm.GetTotal("ASK", "1235");
Assert.True(result.Value == 1231);
此外,您正在嘲笑IDataService并呼叫它sut,sut 將是控制器,SUT通常不會被嘲笑或存根,這又是自以為是... :-)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/345888.html
