Est-il possible de se moquer d'un .NET HttpWebResponse?
j'ai un test d'intégration qui prend des résultat json à partir d'un 3ème partie serveur. C'est très simple et fonctionne très bien.
J'espérais arrêter réellement frapper ce serveur et à l'aide de Moq
(ou tout se moquant de la bibliothèque, comme ninject, etc) afin de détourner et de forcer le résultat de retour.
est-ce possible?
Voici un exemple de code :-
public Foo GoGetSomeJsonForMePleaseKThxBai()
{
//prep stuff ...
//Now get json please.
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("Http://some.fancypants.site/api/hiThere);
httpWebRequest.Method = WebRequestMethods.Http.Get;
string responseText;
using (var httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse())
{
using (var streamReader = new StreamReader(httpWebResponse.GetResponseStream()))
{
json = streamReader.ReadToEnd().ToLowerInvariant();
}
}
//Check the value of the json... etc..
}
et bien sûr, cette méthode est appelée de mon test.
Je pensais que peut-être j'ai besoin de passer par cette méthode (ou une propriété de la classe?) un moqué httpWebResponse
ou quelque chose, mais n'était pas trop sûr si c'était la voie. Aussi, la réponse est une sortie à partir d'une httpWebRequest.GetResponse()
méthode .. donc peut-être que j'ai juste besoin de passer dans un moqué HttpWebRequest
?.
des suggestions avec des exemples de code serait le plus aprreciated!
Vous devez vous connecter pour publier un commentaire.
Vous pouvez changer votre consommation de code à prendre dans une interface d'une usine qui crée les demandes et les réponses qui peuvent être moqué de qui encapsule la mise en œuvre effective.
Mise À Jour: Revisiter
J'ai été faire downvotes de temps après ma réponse a été acceptée, et j'avoue que ma réponse originale à cette question était de mauvaise qualité et a fait un gros hypothèse.
Moqueur HttpWebRequest en 4,5+
La confusion de ma réponse originale à cette question réside dans le fait que vous pouvez se moquer
HttpWebResponse
en 4.5, mais pas les versions antérieures. En se moquant de 4,5 utilise également obsolète constructeurs. Ainsi, le plan d'action recommandé est l'abstraction de la demande et la réponse. De toute façon, ci-dessous est un travail complet de test à l'aide .NET 4.5 Moq 4.2.Meilleure réponse: Résumé de la Réponse et Demande
Voici un endroit plus sûr de bare-bones de la mise en œuvre d'une abstraction qui fonctionne pour les versions précédentes (bien, en baisse à 3,5): au moins
J'ai écrit un ensemble d'interfaces et cartes précisément à cette fin il y a quelques années.
Plutôt que de se moquant de la HttpWebResponse est je voudrais placer l'appel derrière une interface, et se moquer de cette interface.
Si l'on analyse la réponse web frappé le site je le veux aussi, c'est un test que si elle ne classe Un appel de l'WebResponse interface pour obtenir les données nécessaires.
Pour se moquant d'un interface, je préfère Rhino se moque de. Voir ici sur la façon de l'utiliser.
public class AwesomeClass : IThinkICan
. Si vous êtes à la suggestion, je viens de fantaisie qui la classe au lieu de cela, j'ai donc simulé l'objet de retour? Pour l'instant, mon test n'a frappé la 3ème partie, mais je ne veux pas de ça pour le faire. (ie. passer de test d'intégration d'une unité de test).Si ça aide, veuillez trouver ci-dessous le code illustré dans la accepté de répondre à l'aide de NSubstitute en place de Moq
Unité de Test et passe avec succès.
Jusqu'votes sur la réponse que j'ai été la recherche de quelques temps comment le faire efficacement.
var r = Substitute.For<HttpWebResponse>(); Castle.DynamicProxy.InvalidProxyConstructorArgumentsException: Can not instantiate proxy of class: System.Net.HttpWebResponse.
Aucun de Microsoft à l'adresse HTTP de la pile a été développé avec les tests unitaires et de la séparation dans l'esprit.
Vous disposez de trois options:
HttpWebResponse
etHttpWebRequest
par deux autres classes. C'est ce que le MVC équipe a fait avecHttpContext
.Deuxième option:
Vous pouvez effectivement revenir
HttpWebResponse
sans se moquer, voir ma réponse ici. Il ne nécessite pas de "externes" proxy interfaces, seul le "standard"WebRequest
WebResponse
etICreateWebRequest
.Si vous n'avez pas besoin d'accéder à
HttpWebResponse
et peut faire face à toutWebResponse
il est encore plus facile; nous le faisons dans nos tests unitaires pour revenir "préfabriqués" le contenu des réponses à la consommation. J'ai eu à "aller plus loin" afin de rendement réel des codes d'état HTTP, pour simuler par exemple, 404 réponses qui nécessite l'utilisation de laHttpWebResponse
de sorte que vous pouvez accéder à laStatusCode
propriété et coll.Les autres solutions en supposant que tout est
HttpWebXXX
ignore tout pris en charge parWebRequest.Create()
sauf HTTP, qui peut être un traitement pour toute enregistré préfixe que vous avez des soins à utiliser (viaWebRequest.RegisterPrefix()
et si vous êtes ignorant que vous êtes absent dehors, car c'est un excellent moyen de faire découvrir à d'autres flux de contenu vous n'avez aucun moyen d'accès, par exemple Embeeded Ressources Flux de, flux de Fichier, etc.Aussi, explicitement casting le retour de
WebRequest.Create()
àHttpWebRequest
est un chemin d'accès à la rupture, puisque la méthode type de retour estWebRequest
et encore, montre une certaine ignorance de la façon dont cette API fonctionne réellement.J'ai Trouvé une excellente solution dans ce post de blog:
Il est très facile à utiliser, il vous suffit pour ce faire:
Et copier ces fichiers à votre projet:
WebRequest.RegisterPrefix("test", new TestWebRequestCreate());
vous vous inscrivez à un préfixe pour les demandes. Donc, vous avez à se moquer de l'url: à l'aide de test://example.com au lieu de http://example.comHttpWebRequest
. si vous utilisez ce code pour tester le code dans la question, il ne pourrait pas essayer de convertir explicitementTestWebReponse
àHttpWebRequest
. la ligne 4 de sa méthodeTestWebReponse
àHttpWebResponse
etTestWebRequest
àHttpWebRequest
. Dans ce cas vous avez juste à modifier l'héritage deTestWebRequest
etTestWebReponse
d'hériter deHttpWebRequest
etHttpWebResponse
respectivement