Search code examples
c#unit-testingnunitnmock

Unit test with nUnit and nMocks


Bit of a nUnit / nMock / Unit testing noobie question:

I am trying to unit test this class.

I have created a mock of it because I want to know the value returned from "getCurrencyRates", so that I can create tests based on that data.

So I created a mock of this object (just to be able to know the exchange rates returned).

...but now I also want to call some of the other methods on this class.

Should I:

a) somehow call the real methods from the mock object (not even sure if that's possible) b) refactor so that only the web service call is in it's own object and create a mock of that c) something else?

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);
    }
}

Solution

  • Your CurrencyConverter at the moment does two things: converts currencies (which is good) and calls external service to fetch data (which is bad). You want your classes having single, easy definable responsibilities. Your code will be then much cleaner, more managable and, what's important in this context - more testable.

    Refactor your data providing method (getCurrencyRates) to external service (class) and inject it to your converter object (for example via constructor injection).

    Also, why NMocks? It's no longer actively developed (last updates seem to be 4-6 years ago), one might assume it's not as easy to use as modern frameworks, such as FakeItEasy or Moq.