如何用第三方api为Webapi创建单元测试?

本文关键字:创建 单元测试 Webapi 何用 第三方 api | 更新日期: 2023-09-27 18:11:19

我使用Nunit创建单元测试。我有webapi项目,并使用一些第三方api以下是我正在使用的代码块之一。

在下面的函数中,你可以看到我正在返回json数据由facebook图形api返回字符串格式。至于单元测试断言IsEqual检查我的两个比较对象将使用来自相同api的数据,然后我需要匹配它们还是我需要为这种类型的项目做测试。

public  string getfriends(string accesstoken)
        {
            string retVal = "";
            string url = API_BaseUrl + "/me/invitable_friends?&access_token=" + accesstoken;
            System.Net.HttpWebRequest request = System.Net.WebRequest.Create(url) as System.Net.HttpWebRequest;
            System.Net.HttpWebResponse response = null;
            try
            {
                using (response = request.GetResponse() as System.Net.HttpWebResponse)
                {
                    System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream());
                    retVal = reader.ReadToEnd();
                }
            }
            catch (Exception ex)
            {
            }
            return retVal;
        }

如何用第三方api为Webapi创建单元测试?

考虑抽象您的依赖项(在本例中是第三方api)并将它们注入到它们的依赖类中。这将允许更好地模拟你的单元测试,并且总体上更灵活/可维护的架构。

以您当前的函数为例,抽象将看起来像这样。

public interface IFacebookService {
    public string GetFriends();
}
public interface ITokenProvider {
    public string GetAccessToken();
}

其中实现这个接口要有实际的代码来连接到第三方服务。

public class FacebookService : IFacebookService
    private string accesstoken;
    private string API_BaseUrl;
    public FacebookService(ITokenProvider tokens, IUrlProvider urls) {
        accessToken = tokens.GetAccessToken();
        API_BaseUrl = url.GetBaseUrl();
    }
    public  string Getfriends() {
        string retVal = "";
        string url = API_BaseUrl + "/me/invitable_friends?&access_token=" + accesstoken;
        System.Net.HttpWebRequest request = System.Net.WebRequest.Create(url) as System.Net.HttpWebRequest;
        System.Net.HttpWebResponse response = null;
        try {
            using (response = request.GetResponse() as System.Net.HttpWebResponse) {
                System.IO.StreamReader reader = new System.IO.StreamReader(response.GetResponseStream());
                retVal = reader.ReadToEnd();
            }
        }
        catch (Exception ex)
        {
        }
        return retVal;
    }
}

如果你有一个依赖于该服务的API控制器,例如:

public class FriendsController : ApiController {
    IFacebookService facebook;
    public FriendsController(IFacebookService facebook) {
        this.facebook = facebook;
    }
    [HttpGet]
    public IHttpActionResult GetFacebookFriends() {
        var friends = facebook.GetFriends();
        if(!string.IsNullOrWhiteSpace(friends)) {
            return Ok(friends);
        }
        return NotFound("You have no friends. :(");
    }
}

对于独立的单元测试,你现在可以模拟已经被抽象的第三方API。我正在使用Moq来模拟第三方抽象。

[TestClass]
public class FriendsControllerTests {
    [TestMethod]
    public void GetFacebookFriendsTest() {
        //Arrange
        var facebook = Mock.Of<IFacebookService>();
        var facebookMock = Mock.Get(facebook);
        facebookMock.Setup(m => m.GetFriends()).Returns("{json of friends}");
        var sut = new FriendsController(facebook);
        //Act
        var actionResult = sut.GetFacebookFriends();
        //Assert
        //...do your assertions here 
    }
}

上面的测试现在允许您独立测试控制器,而不必直接调用实际的第三方API。

我将抽象出您的消息发送/检索,然后单独进行单元测试&无论哪个类也隔离地包含GetFriends,模拟消息发送/检索。

你应该为所有的项目做单元测试,但是代码需要以这样一种可行的方式来设计。目前,这段代码将很难测试,因为它旋转HttpWebRequests,需要被隔离在某种接口后面,称为IRequestSender之类的东西。我推荐Moq模拟接口,如果没有模拟,你会发现测试就像把你的头撞到墙上。