【问题标题】:HttpGet unit test for sort conditions用于排序条件的 HttpGet 单元测试
【发布时间】:2020-01-10 00:47:19
【问题描述】:

我有以下从端点检索数据的控制器。

它还可以根据是否设置type对数据进行排序。

最好的测试方法是什么?

public class UsersController : ControllerBase
    {

        [HttpGet]
        public async Task<IActionResult> GetAllUsers(string type)
        {
            using (var client = new HttpClient())
            {
                try
                {
                    client.BaseAddress = new Uri("http://demo10102020.mockable.io");
                    var response = await client.GetAsync($"/people");
                    response.EnsureSuccessStatusCode();

                    var stringResult = await response.Content.ReadAsStringAsync();
                    List<User> rawUsers = JsonConvert.DeserializeObject<User[]>(stringResult).ToList();
                    List<User> sortedUsers = rawUsers;
                    if(type == "first-name")
                    {
                        sortedUsers = rawUsers.OrderBy(o => o.FirstName).ToList();
                    }
                    else if(type == "score")
                    {
                        sortedUsers = rawUsers.OrderBy(o => o.Score).ToList();
                    }

                    return Ok(sortedUsers);
                }
                catch (HttpRequestException httpRequestException)
                {
                    return BadRequest($"Error getting users: {httpRequestException.Message}");
                }
            }
        }
    }

这是我目前的方法,我不确定如何模拟 API:

[TestClass]
public class TestPersonController
{
    [TestMethod]
    public void GetAllPersons_ShouldReturnAllProducts()
    {
        var testPersons = GetTestPersons();
        var controller = new PersonController();
    }

    private List<Person> GetTestPersons()
    {
        var testPersons = new List<Person>();
        testPersons.Add(new Person { FirstName = "dfdfdf", Surname = "dfdfdf", Score = 100 });
        testPersons.Add(new Person { FirstName = "dfsdfsfasf", Surname = "safasfsdaf", Score = 200 });
        testPersons.Add(new Person { FirstName = "asffas", Surname = "asdffasdf", Score = 200 });

        return testPersons;
    }
}

【问题讨论】:

  • 您当前(尚未显示)的方法有什么问题?
  • 我假设您使用的是 Newtonsoft JSON 库?只是好奇您没有收到 DeserializeObject 方法可能引发不会在 HttpRequestException 块中捕获的异常的预编译警告。--抱歉,这不能回答您的问题
  • 就您的测试用例而言,将方法GetAllUsers 分成两种方法会更容易——一种处理GetAsync。然后将响应字符串传递给另一个方法进行反序列化。此外,一般建议在方法执行异步操作的任何方法名称中包含“异步”,例如 GetAllUsersAsync()
  • 它也可以排序 SRP 的反例。应该从方法中提取逻辑,以便抽象出与第三方的通信。这样你就可以毫无问题地测试排序逻辑。是否可以选择重构被测代码?

标签: c#


【解决方案1】:

不确定它是否值得,但我会继续,将 api 调用移动到单独的工厂类和排序。控制器仅从您的工厂获取最终值。我可能有一个协调器工厂来调用 api 调用工厂并进行排序。

然后,就可以进行单元测试了

  1. 通过扩展 HttpClient 并创建返回测试/模拟数据的方法的 api 工厂。

  2. 编排器工厂期望字符串列表或输入数据并测试排序后的数据。

  3. 然后是控制器测试

【讨论】:

  • 谢谢,api调用测试会是什么样子?
  • 今天结束前我会分享一些
  • 我终于能够创建一个更接近您正在寻找的东西,但随着我不得不想出的时间在一定程度上概括了。您可以在gitlab.com/AravindK777/friendzardemoapp 找到示例演示代码
【解决方案2】:

只是作为一种观点,我认为你的方法做的事情太多了

我会在另一个方法中调用 Http

例如:

        [HttpGet]
        public async Task <IActionResult> GetAllUsers (string type)
        {
           
                    List <User> rawUsers = UserExternalService.GetAllUser()

                    if (type == "first-name")
                    {
                        return Ok (rawUsers.OrderBy (o => o.FirstName) .ToList ());
                    }
                    else if (type == "score")
                    {
                        return Ok (rawUsers.OrderBy (o => o.Score) .ToList ());
                    }

                    return Ok (rawUsers);
            
        }

This method would take 3 unit test

Example:

        public class The_Method_GetAllUsers
        {
              
            [Fact]
            public async void Should_return_user_when_type_is_name
            {
               Assert.IsType<OkObjectResult>>(this.Sut.GetAllUser("name"));
            }

            [Fact]
            public async void Should_return_user_when_type_is_score
            {
               Assert.IsType <OkObjectResult>>(this.Sut.GetAllUser("score"));
            }

            [Fact]
            public async void Should_return_user_when_type_its_not_name_and_score
            {
               Assert.IsType <OkObjectResult>>(this.Sut.GetAllUser("surname"));
            }
        }

我认为这是一个更清洁的解决方案,它会缺少我们认为仅称为 http 及其 try / catch 的服务的单元测试

模拟HttpClientMock HttpClient using Moq

【讨论】:

    猜你喜欢
    • 2018-06-04
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多