web-dev-qa-db-fra.com

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

J'ai lu certaines des réponses ici concernant les tests de vues et de contrôleurs et les moqueries, mais je ne comprends toujours pas comment tester un contrôleur ASP.NET MVC qui lit et définit les valeurs de la session (ou toute autre variable basée sur le contexte). Comment puis-je fournir un contexte (Session) pour mes méthodes de test? Est-ce que la réponse est moqueuse? Quelqu'un a des exemples? En gros, j'aimerais simuler une session avant d'appeler la méthode du contrôleur et de le faire utiliser par le contrôleur. Des idées?

43
Codewerks

Découvrez le post de Stephen Walther sur le contexte de Fake the Controller:

Astuce ASP.NET MVC N ° 12 - Contexte de simulation 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"]);
}
44
David P

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

Par exemple, voici comment nous gérons les éléments relatifs à l’authentification des formulaires. Nous avons un ISecurityContext:

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

Avec une implémentation 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; }
    }
}
13
chadmyers

Avec MVC RC 1, ControllerContext encapsule 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<ControllerContext>();
context.Expect(x => x.HttpContext.Session["MyKey"]).Return("MyValue");
controller.ControllerContext = context;

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

9
Dane O'Connor

Je trouvais que se moquer était assez facile. Voici un exemple de moquage de httpContextbase (qui contient les objets request, session et response) à l'aide de moq.

[TestMethod]
        public void HowTo_CheckSession_With_TennisApp() {
            var request = new Mock<HttpRequestBase>();
            request.Expect(r => r.HttpMethod).Returns("GET");     

            var httpContext = new Mock<HttpContextBase>();
            var session = new Mock<HttpSessionStateBase>();

            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.

5
Korbin

Scott Hanselman a écrit un article sur la manière de créer un fichier upload quickapp avec MVC.

2
Nick DeVore

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<string, object> dictionary; 

        public CustomSession()
        {
            dictionary = new Dictionary<string, object>();
        }

        public override object this[string 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é créé pour Test d'unité ASP.NET appelé Ivonna .

0
Steve_0