Moq对象总是返回null - 为什么?

时间:2011-07-04 03:05:04

标签: unit-testing moq

我正试图掌握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);
    }

返回值位于资源文件中,是Google的XML输出。现在,当我运行单元测试时,我得到了异常:

  

模拟上的所有调用都必须有相应的设置..

如果我关闭严格模式,则模拟对象返回null。如果我将设置更改为:

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

然后测试运行正常。但我不想测试任何字符串,我想测试这个特定的地址。

请把我从痛苦中解脱出来告诉我哪里出错了。

1 个答案:

答案 0 :(得分:3)

据我所知,当你收到字符串“Brisbane,Australia”时,你的模拟返回值是一个特定值,但你传递的值是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);
…