J'utilise la classe shanselmann's MvcMockHelper pour maqueter des choses HttpContext en utilisant Moq mais le problème que je rencontre est de pouvoir assigner quelque chose à mon objet de session mocké dans mon contrôleur MVC et d'être ensuite capable de lire cette même valeur dans mon test unitaire à des fins de vérification. Ma question est de savoir comment affecter une collection de stockage à l'objet de session mocked pour permettre au code tel que session ["UserName"] = "foo" de conserver la valeur "foo" et doit être disponible dans le test unitaire .Comment moquerez-vous la collection d'objets de session en utilisant Moq
Répondre
J'ai commencé avec MVCMockHelper de Scott Hanselman, ajouté une petite classe et fait les modifications montrées ci-dessous pour permettre au contrôleur d'utiliser Session normalement et le test d'unité pour vérifier les valeurs qui ont été placées par le contrôleur.
/// <summary>
/// A Class to allow simulation of SessionObject
/// </summary>
public class MockHttpSession : HttpSessionStateBase
{
Dictionary<string, object> m_SessionStorage = new Dictionary<string, object>();
public override object this[string name]
{
get { return m_SessionStorage[name]; }
set { m_SessionStorage[name] = value; }
}
}
//In the MVCMockHelpers I modified the FakeHttpContext() method as shown below
public static HttpContextBase FakeHttpContext()
{
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new MockHttpSession();
var server = new Mock<HttpServerUtilityBase>();
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session);
context.Setup(ctx => ctx.Server).Returns(server.Object);
return context.Object;
}
//Now in the unit test i can do
AccountController acct = new AccountController();
acct.SetFakeControllerContext();
acct.SetBusinessObject(mockBO.Object);
RedirectResult results = (RedirectResult)acct.LogOn(userName, password, rememberMe, returnUrl);
Assert.AreEqual(returnUrl, results.Url);
Assert.AreEqual(userName, acct.Session["txtUserName"]);
Assert.IsNotNull(acct.Session["SessionGUID"]);
Ce n'est pas parfait, mais cela fonctionne assez pour les tests.
Je pense que vous pouvez définir une attente sur le faux avec une valeur spécifique, il devrait retourner quoi que ce soit. Les mocks ne sont pas utilisés comme des faux réels mais plutôt comme des choses sur lesquelles vous pouvez affirmer un comportement.
Il semble que vous cherchiez en fait un adaptateur que vous pouvez enrouler autour de la session pour pouvoir fournir une implémentation différente pendant les tests et pendant l'exécution il retournera des éléments de session HttpContext?
Est-ce que cela a du sens?
Je viens de trouver un bel exemple de la fausseté de leur HttpSessionState par l'équipe Oxite et de la maintenance d'une collection SessionStateItemCollection dans ce faux. Cela devrait fonctionner aussi bien qu'un moq dans mon cas.
EDIT:
URL pour cet exemple est http://oxite.codeplex.com/sourcecontrol/changeset/view/33871?projectName=oxite#388065
pour le bénéfice de d'autres trouvant cette question à travers des recherches, pourriez-vous s'il vous plaît poster un lien vers l'information que vous avez trouvé qui répond à la question. –
+1 à un lien pour plus d'informations à ce sujet. –
Je pense qu'il parle de cette classe: http: //oxite.codeplex.com/sourcecontrol/changeset/view/33871? projectName = oxite # 388065 – andrecarlucci
L'utilisation moq 3.0.308.2 est un exemple ici de mon compte la configuration du contrôleur dans mon test unitaire:
private AccountController GetAccountController()
{
.. setup mocked services..
var accountController = new AccountController (..mocked services..);
var controllerContext = new Mock<ControllerContext>();
controllerContext.SetupGet(p => p.HttpContext.Session["test"]).Returns("Hello World");
controllerContext.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(_testEmail);
controllerContext.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);
controllerContext.SetupGet(p => p.HttpContext.Response.Cookies).Returns(new HttpCookieCollection());
controllerContext.Setup (p => p.HttpContext.Request.Form.Get ("ReturnUrl")).Returns ("sample-return-url");
controllerContext.Setup (p => p.HttpContext.Request.Params.Get ("q")).Returns ("sample-search-term");
accountController.ControllerContext = controllerContext.Object;
return accountController;
}
puis au sein de votre contrôleur méthode ce qui suit devrait renvoyer "Hello World"
string test = Session["test"].ToString();
Bonne réponse! C'était exactement ce dont j'avais besoin pour tester les données de ma session. – Rob
Fonctionne parfaitement. Je vous remercie!! –
Je l'ai fait une maquette un peu plus élaborée que la réponse Posté par @RonnBlack
public class HttpSessionStateDictionary : HttpSessionStateBase
{
private readonly NameValueCollection keyCollection = new NameValueCollection();
private readonly Dictionary<string, object> _values = new Dictionary<string, object>();
public override object this[string name]
{
get { return _values.ContainsKey(name) ? _values[name] : null; }
set { _values[name] = value; keyCollection[name] = null;}
}
public override int CodePage
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public override HttpSessionStateBase Contents
{
get { throw new NotImplementedException(); }
}
public override HttpCookieMode CookieMode
{
get { throw new NotImplementedException(); }
}
public override int Count
{
get { return _values.Count; }
}
public override NameObjectCollectionBase.KeysCollection Keys
{
get { return keyCollection.Keys; }
}
public Dictionary<string, object> UnderlyingStore
{
get { return _values; }
}
public override void Abandon()
{
_values.Clear();
}
public override void Add(string name, object value)
{
_values.Add(name, value);
}
public override void Clear()
{
_values.Clear();
}
public override void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public override bool Equals(object obj)
{
return _values.Equals(obj);
}
public override IEnumerator GetEnumerator()
{
return _values.GetEnumerator();
}
public override int GetHashCode()
{
return (_values != null ? _values.GetHashCode() : 0);
}
public override void Remove(string name)
{
_values.Remove(name);
}
public override void RemoveAll()
{
_values.Clear();
}
public override void RemoveAt(int index)
{
throw new NotImplementedException();
}
public override string ToString()
{
return _values.ToString();
}
public bool Equals(HttpSessionStateDictionary other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Equals(other._values, _values);
}
}
mis à jour pour refléter la correction de la propriété ** Keys ** - juste besoin d'une autre collection pour les clés de suivi - per [ ce poste connexe SO] (http://stackoverflow.com/a/13277399/175679) – SliverNinja
Merci, @RonnBlack pour votre solution! Dans mon cas, je continué à obtenir cette exception parce Session.SessionID était nulle:
System.NotImplementedException was unhandled by user code
HResult=-2147467263
Message=The method or operation is not implemented.
Source=System.Web
StackTrace:
at System.Web.HttpSessionStateBase.get_SessionID()
Pour résoudre ce problème je mets en œuvre @ code de RonnBlack cette façon en utilisant le Moq Mock<HttpSessionStateBase>
au lieu de son MockHttpSession:
private readonly MyController controller = new MyController();
[TestFixtureSetUp]
public void Init()
{
var session = new Mock<HttpSessionStateBase>();
session.Setup(s => s.SessionID).Returns(Guid.NewGuid().ToString());
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var server = new Mock<HttpServerUtilityBase>();
// Not working - IsAjaxRequest() is static extension method and cannot be mocked
// request.Setup(x => x.IsAjaxRequest()).Returns(true /* or false */);
// use this
request.SetupGet(x => x.Headers).Returns(
new System.Net.WebHeaderCollection
{
{"X-Requested-With", "XMLHttpRequest"}
});
var context = new Mock<HttpContextBase>();
//context
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(p => p.Request.Url).Returns(new Uri("http://www.mytesturl.com"));
var queryString = new NameValueCollection { { "code", "codeValue" } };
context.SetupGet(r => r.Request.QueryString).Returns(queryString);
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
}
Pour plus de détails, s'il vous plaît voir http://weblogs.asp.net/gunnarpeipman/using-moq-to-mock-asp-net-mvc-httpcontextbase
- 1. Comment se moquer Controller.User en utilisant moq
- 2. Question concernant la configuration du comportement Moq en utilisant Setup()
- 3. classe de retour de la collection nichée en utilisant NHibernate
- 4. Expériences utilisant moq avec VB.Net
- 5. Mocking un changement d'attribut sur un paramètre - en utilisant Moq
- 6. Moq, VB, HttpResponseBase et en-têtes
- 7. en utilisant d'abord() avec une collection générique par la réflexion
- 8. Personnalisé RoleProvider utilisant la session
- 9. Filtrer la collection enfant en utilisant une collection enfant de l'enfant
- 10. Vérifiez la session FB Connect expire en utilisant facebooker
- 11. Comment trier une collection parent et enfant en utilisant Linq?
- 12. Comment concevoir la collection en C#
- 13. Comment filtrer la collection en JPA/JPQL?
- 14. comment implémenter winform session comme timeout de session en particulier
- 15. Comment configurer ceci (Moq Setup)
- 16. Comment convertir un .net type de collection en collection VBA?
- 17. Où est la documentation MOQ?
- 18. Enregistrement de l'interaction sur un point d'inflexion en utilisant un cadre de simulation. Moq
- 19. colonne Accès de la Collection de Collection utilisant le mappage Hibernate
- 20. NHIBERNATE: Comment mapper une collection dans la base de données en utilisant Mapping.Attributes
- 21. Tests unitaires utilisant Moq, code utilisant Linq to Sql pour la procédure stockée
- 22. Recherche base de données en utilisant une collection d'objets entité
- 23. collection de propriétés du système en utilisant le navigateur Web
- 24. En utilisant Moq, comment vérifier toutes les propriétés d'un objet ont été copiées?
- 25. C#, en utilisant lambdas avec initialisation de collection
- 26. pourquoi la collection [Person.companies] n'a pas été traitée par flush() lors de l'utilisation de la session?
- 27. Comment itérer une collection de colonnes Excel en C++ en utilisant Automation?
- 28. Comment utiliser PostSharp avec MOQ?
- 29. Insertion de Setter en utilisant la stratégie d'instance de session nommée avec la structure map
- 30. La meilleure façon d'implémenter un serveur de session en utilisant une base de données?
Merci pour cet exemple, ça a été très utile. J'ai légèrement modifié votre MockHttpSession pour renvoyer null plutôt que de lancer une exception lorsque la clé n'existe pas dans le dictionnaire pour imiter plus étroitement l'objet HttpSession. Juste un conseil pour les autres consommateurs. – DavidWhitney
Exactement ce dont j'avais besoin. +1 – fre0n
J'ai essayé de le faire sans pouvoir actuellement référencer un cadre de simulation, et votre MockHttpSession est le meilleur exemple que j'ai trouvé jusqu'ici. J'ai découvert que changer le getter en tant que tel obtenait {return _sessionStorage.ContainsKey (name)? _sessionStorage [nom]: null; } permettra le test du code qui est écrit comme - if (sessionProperty ["une certaine clé"] == null) {} –