使用nUnit和nMocks进行单元测试

3

关于nUnit/nMock/单元测试方面的问题:

我正在尝试对这个类进行单元测试。

我创建了一个模拟对象,因为我想知道“getCurrencyRates”返回的值,以便可以基于这些数据创建测试。

所以我创建了一个对象的模拟(仅为了知道返回的汇率)。

...但是现在我还想调用该类的其他一些方法。

我应该:

a) 从模拟对象中以某种方式调用真实方法(不确定是否可能)
b) 重新设计,使只有网络服务调用自己的对象,并创建该对象的模拟
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);
    }
}
2个回答

3
您的CurrencyConverter目前有两个功能:转换货币(很好)和调用外部服务来获取数据(不好)。您希望您的类具有单一职责,易于定义的职责。然后您的代码将更加清洁、可管理,并且在这种情况下更容易进行测试。
重新设计您的数据提供方法(getCurrencyRates)为外部服务(类),并通过构造函数注入方式将其注入到您的转换器对象中。

另外,为什么选择 NMocks?它已经不再得到积极开发(最后的更新似乎是 4-6 年前),人们可能认为它不如现代框架易于使用,比如 FakeItEasyMoq


我选择nMock是因为在我使用的nUnit书中提到了它。有哪些限制?我发现你只能模拟一个接口 - https://dev59.com/60XRa4cB1Zd3GeqPqkwt - Positonic

2
你需要做类似 b) 的操作。如果你正在测试一个对象,你不想模拟这个对象本身,而是它的依赖项。
你要模拟的依赖项是调用 web 服务,因为在 nunit 测试中放置真实的 web 服务调用会违反单元测试的原则,并且实现起来非常困难。
为涉及 web 服务调用的部分创建一个接口。
ICurrencyRateService 
{
     CurrencyRateResponse GetCurrencyRates()
}

然后将所有的webservicey代码放入一个实现此功能的对象中。

这样可以测试ConvertCurrency,也可以更好地将各个对象分离,您有一个对象调用webservice,另一个对象执行计算操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接