Domanda

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);
    }
}
È stato utile?

Soluzione

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.

Altri suggerimenti

you'll want to do something like b). If you're testing an object, you don't want to mock the object itself, but its dependencies.

The dependency you want to mock out is the call to the web service as putting a real webservice call in a nunit test would violate what a unit test is, as well as being a nightmare to implement.

Create an interface for the part involving the webserice call

ICurrencyRateService 
{
     CurrencyRateResponse GetCurrencyRates()
}

and then get all the webservicey code into an object which implements this.

that should allow you to test ConvertCurrency. It also will mean that there is better seperation of concerns between your objects, you have one object which calls a webservice, and one object that does a calculation.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top