簡體   English   中英

使用 xUnit 測試控制器

[英]Testing controller with xUnit

我有 webapi,它需要調用其他端點並獲取數據。

我目前的代碼如下

//http客戶端實現

public interface IHttpClientFactory
{
    HttpClient Create();
}

public class HttpClientFactory : IHttpClientFactory
{
    private readonly ApplicationSettings _applicationSettings;
    HttpClient _httpClient;

    public HttpClientFactory(IOptions<ApplicationSettings> settings)
    {
        _applicationSettings = settings.Value;
    }
    public HttpClient Create()
    {
        if (_httpClient != null)
            return _httpClient;

        var client = new HttpClient()
        {
            BaseAddress = new Uri($"{_applicationSettings.BaseUrl}")
        };
        _httpClient = client;
        return _httpClient;
    }
}

 public interface IGetItemsQuery
{
    Task<IEnumerable<T>> Execute<T>(string url);
}

public class GetItemQuery: IGetItemsQuery
{
    private readonly IHttpClientFactory _httpClientFactory;
    public GetPhotosQuery(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public async Task<IEnumerable<T>> Execute<T>(string url)
    {
        using (var response = await _httpClientFactory.Create().GetAsync($"{url}").ConfigureAwait(false))
        {
            response.EnsureSuccessStatusCode();
            var resp = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            var items = JArray.Parse(resp);
            return items.ToObject<T[]>();
        }
    }

在我的控制器部分

   private readonly IGetItemsQuery _getItemsQuery;

       public HomeController(IGetItemsQuery getItemsQuery)
    {
        _getItemsQuery = getItemsQuery;
    }

 appsettings

     "ApplicationSettings": {
      "BaseUrl": "http://someendpoint.com/"

}

啟動

   services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));
        services.AddScoped<IGetItemsQuery, GetPhotosQuery>();
        services.AddScoped<IHttpClientFactory, HttpClientFactory>();

我想在我的測試中嘗試如下

     [Fact]
    public void Test_Index()
    {
        // Arrange
        var itemsQuery = new Mock<IGetItemsQuery>();
        var controller = new HomeController(itemsQuery.Object);

        // Act
        var result = controller.Index();

        // Assert
        var viewResult = Assert.IsType<ViewResult>(result);
        Assert.Null(viewResult.ViewName);
    }

這是在創建模擬 IGetItemsQuery 但這不是模擬實際的 IHttpClientFactory。

有沒有辦法做到這一點

根據您的抽象依賴項設計,無需模擬客戶端工廠以對控制器進行單元測試。

正如您在測試中所做的那樣,您模擬了IGetItemsQuery ,但是您沒有將它設置為在測試中調用時按預期運行。

例如,如果被測控制器方法看起來像這樣

private readonly IGetItemsQuery getItemsQuery;

public HomeController(IGetItemsQuery getItemsQuery) {
    this.getItemsQuery = getItemsQuery;
}

public async Task<IActionResult> Index() {
    var url = "....";

    var items = await getItemsQuery.Execute<MyItem>(url);

    return View(items);
}

然后,作為被測方法的Index操作的獨立單元測試可能看起來像

[Fact]
public async Task Index_Should_Return_View_With_Items() {
    // Arrange
    var itemsQuery = new Mock<IGetItemsQuery>();

    var items = new MyItem[] {
        new MyItem(),
        new MyItem()
    };

    itemsQuery.Setup(_ => _.Execute<MyItem>(It.IsAny<string>()))
        .ReturnsAsync(items);

    var controller = new HomeController(itemsQuery.Object);

    // Act
    var result = await controller.Index();

    // Assert        
    var viewResult = Assert.IsType<ViewResult>(result);
    Assert.Null(viewResult.ViewName);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM