ASP / NET MVC: Contrôleurs de test avec sessions? Railleur?

J’ai lu certaines des réponses ici: test des vues et des contrôleurs, et moqueur, mais je n’arrive toujours pas à comprendre comment tester un contrôleur ASP.NET MVC qui lit et définit les valeurs de session (ou toute autre variable basée sur le contexte). Comment puis-je fournir un contexte (de session) pour mes méthodes de test? Se moquer de la réponse? Quelqu’un a des exemples? En gros, je voudrais simuler une session avant d’appeler la méthode du contrôleur et demander au contrôleur d’utiliser cette session. Des idées?

Découvrez le post de Stephen Walther sur Faking the Controller Context:

ASP.NET MVC Astuce n ° 12 – Faux le contexte du contrôleur

[TestMethod] public void TestSessionState() { // Create controller var controller = new HomeController(); // Create fake Controller Context var sessionItems = new SessionStateItemCollection(); sessionItems["item1"] = "wow!"; controller.ControllerContext = new FakeControllerContext(controller, sessionItems); var result = controller.TestSession() as ViewResult; // Assert Assert.AreEqual("wow!", result.ViewData["item1"]); // Assert Assert.AreEqual("cool!", controller.HttpContext.Session["item2"]); } 

Le framework ASP.NET MVC n’est pas très convivial (ou plutôt nécessite trop de configuration pour se moquer correctement, et provoque trop de frictions lors des tests, à mon humble avis) en raison de l’utilisation de classes de base abstraites au lieu d’interfaces. Nous avons eu de la chance d’écrire des abstractions pour le stockage par requête et par session. Nous gardons ces abstractions très légères et nos contrôleurs dépendent de ces abstractions pour le stockage par demande ou par session.

Par exemple, voici comment nous gérons les formulaires d’authentification. Nous avons un contexte ISecurity:

 public interface ISecurityContext { bool IsAuthenticated { get; } IIdentity CurrentIdentity { get; } IPrincipal CurrentUser { get; set; } } 

Avec une mise en œuvre concrète comme:

 public class SecurityContext : ISecurityContext { private readonly HttpContext _context; public SecurityContext() { _context = HttpContext.Current; } public bool IsAuthenticated { get { return _context.Request.IsAuthenticated; } } public IIdentity CurrentIdentity { get { return _context.User.Identity; } } public IPrincipal CurrentUser { get { return _context.User; } set { _context.User = value; } } } 

Avec MVC RC 1, le ControllerContext enveloppe le HttpContext et l’expose en tant que propriété. Cela rend beaucoup plus facile de se moquer. Pour simuler une variable de session avec Moq, procédez comme suit:

 var controller = new HomeController(); var context = MockRepository.GenerateStub(); context.Expect(x => x.HttpContext.Session["MyKey"]).Return("MyValue"); controller.ControllerContext = context; 

Voir l’article de Scott Gu pour plus de détails.

J’ai trouvé moqueur d’être assez facile. Voici un exemple de moquage de httpContextbase (qui contient les objects requête, session et réponse) en utilisant moq.

 [TestMethod] public void HowTo_CheckSession_With_TennisApp() { var request = new Mock(); request.Expect(r => r.HttpMethod).Returns("GET"); var httpContext = new Mock(); var session = new Mock(); httpContext.Expect(c => c.Request).Returns(request.Object); httpContext.Expect(c => c.Session).Returns(session.Object); session.Expect(c => c.Add("test", "something here")); var playerController = new NewPlayerSignupController(); memberController.ControllerContext = new ControllerContext(new RequestContext(httpContext.Object, new RouteData()), playerController); session.VerifyAll(); // function is trying to add the desired item to the session in the constructor //TODO: Add Assertions } 

J’espère que cela pourra aider.

Scott Hanselman a écrit un article sur la façon de créer une application rapide de téléchargement de fichiers avec MVC et discute de la façon de falsifier et traite spécifiquement de “Comment se moquer de choses qui ne sont pas faciles à manipuler”.

J’ai utilisé la solution suivante: créer un contrôleur dont tous mes autres contrôleurs héritent.

 public class TestableController : Controller { public new HttpSessionStateBase Session { get { if (session == null) { session = base.Session ?? new CustomSession(); } return session; } } private HttpSessionStateBase session; public class CustomSession : HttpSessionStateBase { private readonly Dictionary dictionary; public CustomSession() { dictionary = new Dictionary(); } public override object this[ssortingng name] { get { if (dictionary.ContainsKey(name)) { return dictionary[name]; } else { return null; } } set { if (!dictionary.ContainsKey(name)) { dictionary.Add(name, value); } else { dictionary[name] = value; } } } //TODO: implement other methods here as needed to forefil the needs of the Session object. the above implementation was fine for my needs. } } 

Ensuite, utilisez le code comme suit:

 public class MyController : TestableController { } 

Comme HttpContext est statique, j’utilise Typemock Isolator pour le simuler, Typemock a également un complément personnalisé conçu pour les tests unitaires ASP.NET appelé Ivonna .