远程API调用的单元测试,如何与JSON对象一起使用

时间:2019-02-18 15:21:18

标签: json unit-testing asp.net-web-api controller nunit

在我的Web api中,我有一个方法可以调用返回反序列化JSON对象的服务。我找不到适合我的单元测试方法。 以下是来自控制器的代码:

     [RequireHttps]
     [Route("api/GetItem/{id}")]
     public class GetItemController : ControllerBase
    {
     private static HttpClient client = new HttpClient();
     private Item item = new Item();

     [RequireHttps]
     [Route("api/GetItem/{id}")]
     public Item GetItem(string name, string password)
     {
        string url = "https://localhost:5001/";


       string uri = url + "api/item/" + name+ "/" +  password "/"  ;
       client.DefaultRequestHeaders.Accept.Add(new 
       MediaTypeWithQualityHeaderValue("application/json"));
       HttpResponseMessage Res = client.GetAsync(uri).Result;              

            if (Res.IsSuccessStatusCode)
            {

                var MemResponse = Res.Content.ReadAsStringAsync().Result;

                member = JsonConvert.DeserializeObject<Item> 
                (MemResponse);

            }

            return Ok(item);
        }
    }

我编写的单元测试应该检查错误的用户名和密码,但是在运行测试时,它只会显示为灰色,并且永远不会运行

  [TestMethod]
   public void GetItemWithWrongPassword()
   {      
    var username = "Hellow";
    var pass = "There";
    var controller = new GetItemController();
    var response = controller.GetItem(username, pass);
    var s = response.ToString();
    Assert.AreEqual(s, "System.Web.Http.Results.NotFoundResult");
}

我做错了什么? 稍后,我想测试是否连接到远程API。

1 个答案:

答案 0 :(得分:0)

创建GetItemController的实例并调用其方法不是一个好主意,因为在此过程中会跳过整个消息管道。

我在这里看到两个选项:

  1. HttpClient中包含的代码(包括GetItem)放入另一个类,并在该类的实例上调用该方法,例如:

    public class ItemClient
    {
        private static HttpClient client = new HttpClient();            
    
        public Item GetItem(string name, string password)
        {
            Item item = null;
            string url = "https://localhost:5001/";
            string uri = url + "api/item/" + name + "/" + password;
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage Res = client.GetAsync(uri).Result;              
    
            if (Res.IsSuccessStatusCode)
            {
                var MemResponse = Res.Content.ReadAsStringAsync().Result;
                item = JsonConvert.DeserializeObject<Item>(MemResponse);
            }
            return item;
        }
    }
    

    控制器方法:

    [RequireHttps]
    [Route("api/GetItem/{name}/{password}")]
    public Item GetItem(string name, string password)
    {
        ItemClient client = new ItemClient();
        var item = client.GetItem(name, password);
        return Ok(item);
    }
    

    测试方法:

    [TestMethod]
    public void GetItemWithWrongPassword()
    {      
        var username = "Hellow";
        var password = "There";
        ItemClient client = new ItemClient();
        var item = client.GetItem(username, password);
        Assert.IsNull(item);
    }
    
  2. 在测试方法中使用HttpClient调用控制器方法:

    [TestMethod]
    public void GetItemWithWrongPassword()
    {      
        var username = "Hellow";
        var password = "There";
    
        string url = "https://localhost/"; // Host of your Web API
    
        string uri = url + "api/GetItemController/GetItem/" + username + "/" + password;
        HttpClient client = new HttpClient(); 
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        HttpResponseMessage Res = client.GetAsync(uri).Result;              
        var s = Res.ToString();
        Assert.AreEqual(s, "System.Web.Http.Results.NotFoundResult");
    }
    

由于两个好处,我个人更喜欢选项1:

  1. 调试测试更加容易。通过HttpClient调试呼叫(选项2) 通常意味着您必须启动Visual的第二个实例 在Studio中设置一个断点。

  2. 该代码可以在不是Web API服务的其他项目中使用。端点变成了围绕实际业务逻辑的简单包装。