Moq объект всегда возвращает ноль - почему? - PullRequest
0 голосов
/ 04 июля 2011

Я пытаюсь разобраться с Moq и использую простой пример, чтобы понять это.Я использую Google для геокодирования адреса.Я обернул WebClient, так что он может быть подделан.Вот код:

public class Position
{
    public Position(double latitude, double longitude)
    {
        Latitude = latitude;
        Longitude = longitude;
    }
    public virtual double Latitude { get; private set; }
    public virtual double Longitude { get; private set; }
}

public interface IWebDownloader
{
    string Download(string address);
}

public class WebDownloader : IWebDownloader
{
    public WebDownloader()
    {
        WebProxy wp = new WebProxy("proxy", 8080);
        wp.Credentials = new NetworkCredential("user", "password", "domain");

        _webClient = new WebClient();
        _webClient.Proxy = wp;
    }

    private WebClient _webClient = null;

    #region IWebDownloader Members

    public string Download(string address)
    {
        return Encoding.ASCII.GetString(_webClient.DownloadData(address));
    }

    #endregion
}

public class Geocoder
{
    public Position GetPosition(string address, IWebDownloader downloader)
    {
        string url = string.Format("http://maps.googleapis.com/maps/api/geocode/xml?address={0}&sensor=false",
                                   address);
        string xml = downloader.Download(url);

        XDocument doc = XDocument.Parse(xml);

        var position = from p in doc.Descendants("location")
                       select new Position(
                           double.Parse(p.Element("lat").Value),
                           double.Parse(p.Element("lng").Value)
                           );

        return position.First();
    }
}

Пока все хорошо.Теперь вот модульный тест с Moq:

    [TestMethod()]
    public void GetPositionTest()
    {
        Mock<IWebDownloader> mockDownloader = new Mock<IWebDownloader>(MockBehavior.Strict);
        const string address = "Brisbane, Australia";
        mockDownloader.Setup(w => w.Download(address)).Returns(Resource1.addressXml);

        IWebDownloader mockObject = mockDownloader.Object;

        Geocoder geocoder = new Geocoder();
        Position position = geocoder.GetPosition(address, mockObject);

        Assert.AreEqual(position.Latitude , -27.3611890);
        Assert.AreEqual(position.Longitude, 152.9831570);
    }

Возвращаемое значение находится в файле ресурсов и является выводом XML от Google.Теперь, когда я запускаю модульный тест, я получаю исключение:

Все вызовы на макете должны иметь соответствующую настройку.

Если я отключу строгий режим, тогдафиктивный объект возвращает ноль.Если я изменю настройку на:

mockDownloader.Setup(w => w.Download(It.IsAny<string>())).Returns(Resource1.addressXml);

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

Пожалуйста, избавь меня от страданий и скажи, где я иду не так.

1 Ответ

3 голосов
/ 04 июля 2011

Насколько я могу судить, вы заставляете ваш макет возвращать определенное значение, когда он получает строку "Брисбен, Австралия", но вы передаете ему значение http://maps.googleapis.com/maps/api/geocode/xml?address=Brisbane,%20Australia&sensor=false (или, тем не менее, в конечном итоге оно форматируется).

Попробуйте что-то подобное в своем тестовом коде:

…
const string address = "Brisbane, Australia";
const string url = string.Format("http://maps.googleapis.com/maps/api/geocode/xml?address={0}&sensor=false", address);
mockDownloader.Setup(w => w.Download(url)).Returns(Resource1.addressXml);
…
...