我正在使用Nunit来创建单元测试。我正在使用webapi项目并使用一些第三方api。下面是我正在使用的代码块之一。
在下面的函数中,你可以看到我正在以字符串格式返回facebook graph api返回的json数据。至于单元测试断言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;
}
答案 0 :(得分:4)
查看抽象依赖项(在本例中为第三方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。
答案 1 :(得分:2)
我将你的信息发送/检索抽象出来,然后单独进行单独测试。无论哪个类都孤立地包含你的GetFriends,嘲笑发送/检索的消息。
您应该对所有项目进行单元测试,但代码需要以可行的方式进行设计。目前这个代码很难测试,因为它正在启动HttpWebRequests,它需要被隔离在某种界面后面,称为IRequestSender。我建议Moq嘲笑接口,不要嘲笑你会发现测试就像撞墙一样。