2011-02-17 2 views
7

Comme le suggère Richard Willis dans http://blog.salamandersoft.co.uk/index.php/2009/10/how-to-mock-httpwebrequest-when-unit-testing/ j'essaye d'appeler une requête Web en masquant le comportement. Pour cela (je me demande si je suis en train de déconner quelque chose ici), j'ai implémenté IWebRequestCreate et étendu une requête WebRequest et une réponse WebResponse. (plus de détails dans les codes de lien)Utilisation de .Net WebRequest Factory

Mais maintenant, dans mon code que j'ai eu un test registre (WebRequest.RegisterPrefix) un préfixe:

[Test] 
public void Test() { 
    var some = File.ReadAllBytes(@"TestData\WebService\admrond_13jan2011_14jan2011.xml"); 
    WebRequest.RegisterPrefix("mockPrefix", new WebRequestCreateMock()); 
    WebRequestFake request = WebRequestCreateMock.CreateRequestFake(some); 

    _remoteRepository.PopulateWithMeterData(_meter); 
    ... (error in line before) 

Ensuite, je suis arrivé cette erreur: Invalid URI: The hostname could not be parsed.

Mais pourquoi? Dans mon PopulateWithMeterData(Meter meter) j'ai cet appel:

 WebRequest request = WebRequest.Create(urlListMeteringData); 
    WebResponse ws = request.GetResponse(); 

Quelques suggestions? Est-ce que poster des implémentations de classe est intéressant?


EDIT: comme @Matthew demander:

public class WebRequestCreateMock : IWebRequestCreate { 

    static WebRequest _nextRequest; 
    static readonly object LockObject = new object(); 

    static public WebRequest NextRequest { 
     get { return _nextRequest; } 
     set { 
      lock (LockObject) { 
       _nextRequest = value; 
      } 
     } 
    } 

    public WebRequest Create(Uri uri) { 
     return _nextRequest; 
    } 

    public static WebRequestFake CreateRequestFake(byte[] xmlStream) { 
     WebRequestFake webRequestFake = new WebRequestFake(xmlStream); 
     NextRequest = webRequestFake; 
     return webRequestFake; 
    } 

} 

public class WebRequestFake : WebRequest { 
    MemoryStream requestStream = new MemoryStream(); 
    MemoryStream responseStream; 

    public override string Method { get; set; } 
    public override string ContentType { get; set; } 
    public override long ContentLength { get; set; } 

    public WebRequestFake(byte[] response) { 
     responseStream = new MemoryStream(response); 
    } 

    public override Stream GetRequestStream() { 
     return requestStream; 
    } 

    public override WebResponse GetResponse() { 
     return new WebReponseFake(responseStream); 
    } 
} 

public class WebReponseFake : WebResponse { 

    private readonly Stream _responseStream; 

    public WebReponseFake(Stream responseStream) { 
     _responseStream = responseStream; 
    } 

    public override Stream GetResponseStream() { 
     return _responseStream; 
    } 
} 

Et l'URL est quelque chose comme: mockPrefix://NoMatterUrl

+0

Je développerais davantage votre code et donnerais un exemple de l'URL que vous utilisez pour créer votre requête. –

+0

@Custodio Je veux utiliser le lien rtmp pour le transmettre à HTTPHanlder pour la source vidéo cible du plugin vlc. Pouvez-vous m'aider comment utiliser votre code en lisant des flux en direct à vlc plugin player [Ma question ici] (http://stackoverflow.com/questions/21862260/http-handler-returns-target-source-for-vlc-plugin -joueur) – ZahidKakar

Répondre

3

Comme l'erreur est "Invalid URI: le nom d'hôte n'a pas pu être analysé." vous avez probablement vissé votre Uri "mockPrefix: // NoMatterUrl"

J'ai eu ce problème une fois parce que j'ai oublié d'ajouter un "/" entre le domaine uri et les paramètres de la demande.

Pouvez-vous publier exactement à quoi ressemble votre "NoMatterUri"?

+0

Parfait, je jouais l'url, le débogage j'ai eu: 'mockPrefix: // NoMatterUrlADM_ROND & datainicio = 20090101000000 & datafim = 20090102000000. Donc, je mets un"/"après' NoMatterUrl' et tout fonctionne bien! – Custodio

1

Vous devez enregistrer votre préfixe avec deux points (':'); comme dans:

WebRequest.RegisterPrefix("mockPrefix:", new WebRequestCreateMock()); 
+0

Un bon! J'ai essayé avec le colon aussi. Ne fonctionne pas :( – Custodio

0

J'ai trouvé qu'il est nécessaire d'inclure un "/" de fin dans le préfixe. Par exemple, "test://localhost/":

[TestClass] 
public class WebRequestTests 
{ 
    [TestMethod] 
    public void TestWebRequestCreate() 
    { 
     const string uriString = "test://localhost/foo/bar.baz?a=b&c=d"; 
     var webRequest = new MockWebRequestCreateAssertUrl(uriString); 
     Assert.IsTrue(WebRequest.RegisterPrefix("test://localhost/", webRequest), 
         "Failed to register prefix"); 
     Assert.IsNotNull(WebRequest.Create(uriString)); 
    } 

    public class MockWebRequestCreateAssertUrl : IWebRequestCreate 
    { 
     private readonly Uri _expectedUri; 

     public MockWebRequestCreateAssertUrl(string uriString) 
     { 
      _expectedUri = new Uri(uriString); 
     } 

     public WebRequest Create(Uri uri) 
     { 
      Assert.AreEqual(_expectedUri, uri, "uri parameter is wrong"); 
      return new MockWebRequestAssertUrl(); 
     } 
    } 

    public class MockWebRequestAssertUrl : WebRequest {} 
}