2011-07-04 19 views
0

私はMoqを把握し、簡単な例を使って把握しようとしています。 Googleは住所をジオコードするためにGoogleを使用しています。私はそれが嘲笑されるようにWebClientをラップしました。コードは次のとおりです。Moqオブジェクトは常にnullを返します - なぜですか?

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出力です。今、私はユニットテストを実行したとき、私は例外を取得:私はstrictモードをオフにした場合

モック上のすべての呼び出しは、対応するセットアップを持っている必要があります。..

、その後、モックオブジェクトがnullを返します。セットアップを次のように変更した場合:

この場合、テストは正常に実行されます。しかし、私は任意の文字列をテストしたくない、私はこの特定のアドレスをテストしたい。

私を悲惨さから置き去りにして、どこに間違っているのかを教えてください。

答えて

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); 
… 
+0

Arrgggggghhh、あなたは正しいです。 私はそれを見つけられなかったと信じられません。私は「住所」という言葉の意味を混同していました。 ありがとうございました。 – Gumby

+1

私はテストでString.Format呼び出しを避けることをお勧めします。これはほんの一例ですが、SUT内の正確なロジックを表しています。そのロジックにバグがある場合は、テストにバグがあります。掘る? – bryanbcook

関連する問題