nUnit / nMock / Unit测试noobie问题:
我正在尝试对这个班级进行单元测试。
我已经创建了一个模拟器,因为我想知道“getCurrencyRates”返回的值,这样我就可以根据这些数据创建测试。
所以我创建了一个这个对象的模拟(只是为了能够知道返回的汇率)。
...但现在我也想在这个类上调用其他一些方法。
我应该:
a)以某种方式从模拟对象中调用实际方法(甚至不确定是否可行) b)重构,以便只有Web服务调用在它自己的对象中并创建一个模拟 c)其他什么?
public class CurrencyConversion : ICurrencyConversion
{
public decimal convertCurrency(string fromCurrency, string toCurrency, decimal amount)
{
CurrencyRateResponse rates = getCurrencyRates();
var fromRate = getRate(rates, fromCurrency);
var toRate = getRate(rates, toCurrency);
decimal toCurrencyAmount = toRate / fromRate * amount;
return toCurrencyAmount;
}
public int addNumbers(int i, int j)
{
return i + j;
}
public decimal getRate(CurrencyRateResponse rates, string fromCurrency)
{
if (rates.rates.ContainsKey(fromCurrency))
{
return rates.rates[fromCurrency];
}
else
{
return 0;
}
}
public CurrencyRateResponse getCurrencyRates()
{
HttpWebRequest webRequest = GetWebRequest("http://openexchangeerates.org/latest.json");
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
string jsonResponse = string.Empty;
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
{
jsonResponse = sr.ReadToEnd();
}
var serializer = new JavaScriptSerializer();
CurrencyRateResponse rateResponse = serializer.Deserialize<CurrencyRateResponse>(jsonResponse);
return rateResponse;
}
public HttpWebRequest GetWebRequest(string formattedUri)
{
// Create the request’s URI.
Uri serviceUri = new Uri(formattedUri, UriKind.Absolute);
// Return the HttpWebRequest.
return (HttpWebRequest)System.Net.WebRequest.Create(serviceUri);
}
}
答案 0 :(得分:3)
目前您的CurrencyConverter
两件事:转换货币(这很好)并调用外部服务来获取数据(这很糟糕)。您希望您的课程具有 single ,易于确定的职责。您的代码将更清晰,更易于管理,并且在这种情况下重要的是 - 更可测试。
将数据提供方法(getCurrencyRates
)重构为外部服务(类),并将inject重构为转换器对象(例如,通过构造函数注入)。
另外,为什么要NMocks?它不再被积极开发(最近的更新似乎是4-6 years ago),人们可能会认为它不像现代框架那样容易使用,例如FakeItEasy或Moq。
答案 1 :(得分:2)
你会想做像b)这样的事情。如果您正在测试对象,则不希望模拟对象本身,而是依赖于它。
您要模拟的依赖项是对Web服务的调用,因为在nunit测试中放置真正的Web服务调用会违反单元测试,并且是实现的噩梦。
为涉及webserice调用的部分创建一个接口
ICurrencyRateService
{
CurrencyRateResponse GetCurrencyRates()
}
然后将所有webservicey代码放入一个实现此目的的对象中。
应该允许您测试ConvertCurrency。它还意味着您的对象之间可以更好地分离关注点,您有一个调用Web服务的对象,以及一个执行计算的对象。