Юнит тест с nUnit и nMocks - PullRequest
       40

Юнит тест с nUnit и nMocks

3 голосов
/ 15 февраля 2012

Бит noobie вопроса nUnit / nMock / Unit testing:

Я пытаюсь провести модульное тестирование этого класса.

Я создал его, потому что хочу узнать значение, возвращаемое из "getCurrencyRates", чтобы я мог создавать тесты на основе этих данных.

Итак, я создал макет этого объекта (просто для того, чтобы узнать возвращенные обменные курсы).

... но теперь я также хочу вызвать некоторые другие методы этого класса.

Должен ли я:

а) как-то вызвать реальные методы из фиктивного объекта (даже не уверен, если это возможно) б) рефакторинг так, чтобы только вызов веб-службы находился в его собственном объекте и создавал макет этого в) что-то еще?

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 голосов
/ 15 февраля 2012

Ваш CurrencyConverter на данный момент делает две вещи : конвертирует валюты (что хорошо) и вызывает внешнюю службу для получения данных (что плохо). Вы хотите, чтобы у ваших занятий были одиночные , легко определяемые обязанности. Ваш код будет намного чище, более управляемым и, что важно в этом контексте - более тестируемым.

Рефакторизовать ваш метод предоставления данных (getCurrencyRates) для внешней службы (класса) и внедрить его в ваш объект преобразователя (например, через инжекция в конструктор ).

Кроме того, почему NMocks? Он больше не разрабатывается активно (последние обновления кажутся 4-6 лет назад ), можно предположить, что его не так просто использовать, как современные фреймворки, такие как FakeItEasy или Moq .

2 голосов
/ 15 февраля 2012

вы хотите сделать что-то вроде б). Если вы тестируете объект, вы не хотите издеваться над самим объектом, а над его зависимостями.

Зависимость, которую вы хотите смоделировать, - это вызов веб-службы, поскольку введение реального вызова веб-службы в тест единичного объекта нарушит сам принцип юнит-теста, а также станет кошмаром для реализации.

Создать интерфейс для части, включающей вызов веб-службы

ICurrencyRateService 
{
     CurrencyRateResponse GetCurrencyRates()
}

и затем получить весь веб-сервисный код в объект, который реализует это.

, что должно позволить вам протестировать ConvertCurrency. Это также будет означать, что между вашими объектами лучше разделять проблемы, у вас есть один объект, который вызывает веб-сервис, и один объект, который выполняет вычисления.

...