Pourquoi est-ce que mon asp.net mvc contrôleur appelle pas ça de la classe de base de la méthode Initialize pendant les tests unitaires?
Je tente de l'unité de test de mon contrôleurs, et je suis en utilisant la valeur par défaut MVC 3 AccountController
des tests unitaires. Jusqu'à présent j'ai mon contrôleur, qui ressemble à:
public partial class HomeController : MyBaseController
{
public HomeController(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; }
public virtual ActionResult Index()
{
return View();
}
public virtual ActionResult About()
{
return View();
}
}
MyBaseController
a le code suivant:
public class MyBaseController : Controller
{
public MyJobLeadsBaseController()
{
CurrentUserId = 0;
}
protected override void Initialize(RequestContext requestContext)
{
if (MembershipService == null) { MembershipService = new AccountMembershipService(); }
base.Initialize(requestContext);
//If the user is logged in, retrieve their login id
var user = MembershipService.GetUser();
if (user != null)
CurrentUserId = (int)user.ProviderUserKey;
}
public int CurrentUserId { get; set; }
public IMembershipService MembershipService { get; set; }
protected IUnitOfWork _unitOfWork;
}
Tout fonctionne correctement quand je lance le site réel, et les points d'arrêt de montrer que la Initialize()
est correctement déclenché. Cependant, la suite du test de l'unité n'est jamais à l' Initialize(RequestContext)
méthode:
[TestMethod]
public void Index_Shows_When_Not_Logged_In()
{
//Setup
HomeController controller = new HomeController(_unitOfWork);
controller.MembershipService = new MockMembershipService(null);
SetupController(controller);
//Act
ActionResult result = controller.Index();
//Verify
Assert.IsNotNull(result, "Index returned a null action result");
Assert.IsInstanceOfType(result, typeof(ViewResult), "Index did not return a view result");
}
protected static void SetupController(Controller controller)
{
RequestContext requestContext = new RequestContext(new MockHttpContext(), new RouteData());
controller.Url = new UrlHelper(requestContext);
controller.ControllerContext = new ControllerContext
{
Controller = controller,
RequestContext = requestContext
};
}
De débogage à travers ce test montre qu'à aucun moment le substituée MyBaseController.Initialize()
appelée à tous. Cela provoque des problèmes d'où mon CurrentUserId
propriété n'est pas définie dans les tests unitaires, mais est mis sur le système live.
Quoi d'autre dois-je faire pour déclencher la Initialize()
d'être appelé?
OriginalL'auteur KallDrexx | 2011-03-31
Vous devez vous connecter pour publier un commentaire.
Lorsque vous faites une demande pour un contrôleur à travers un site web sur le framework MVC ramasse que la demande et l'exécute par le biais d'un certain nombre de différentes étapes. Quelque part dans ce pipeline de mesures MVC sait qu'il doit appeler le
Initialize
méthode de manière à ce qu'il trouve leInitialize
dans votreMyBaseController
classe et l'exécute. À ce stade, tout est bien et tout fonctionne.Lorsque vous créez une nouvelle instance de votre
HomeController
dans votre code de test que vous êtes tout simplement la création d'une nouvelle instance d'une classe. Vous n'êtes pas en cours d'exécution qui classe par le biais de la MVC pipeline de demande et de votre framework de test ne sais pas pour exécuter leInitialize
méthode de sorte que vous obtenez un message d'erreur.Personnellement je veux le regarder pour tester les
Index
action indépendamment de laInitialize
méthode. VotreIndex
action ci-dessus est vide donc je ne vois pas exactement ce que vous essayez de faire, mais si vous retournez un point de vue pour les utilisateurs enregistrés et un autre pour les utilisateurs anonymes que je ferais quelque chose comme ceci:Il y a quelques assez chouette de tester les aides dans le MVC contrib projet (http://mvccontrib.codeplex.com/) qui vous permettent de faire des choses comme:
OriginalL'auteur AndyM
Le constructeur n'appelle pas Initialiser. Autant que je me souvienne de Ce que les appels initialiser le Exécuter/ExecuteCore méthode.
Voici le code à partir de la MVC source:
C'est essentiellement appelé à partir de la MvcHandler dans le BeginProcessRequest méthode.
Mise à jour:
RequestContext n'existe pas dans un test unitaire, car vous n'allez par le biais de ASP.NET. Si je me souviens bien, vous avez besoin de s'en moquer.
Un autre problème dans l'utilisation de l'Initialiser dans un test, c'est le fournisseur d'appartenances, que je n'ai pas utilisé moi-même, mais je suppose que AccountMembershipService échouerait vous dans un test? Il me semble que cela permettrait de créer fragile tests. Il serait sans doute également vous ralentir si il a de communiquer avec un serveur, et peut-être ne vous sur un serveur CI.
De l'OMI,à partir d'une base de regarder autour de la méthode Init, il ne devrait pas être là. La solution la plus simple,sans rien casser, qui vient à l'esprit est d'utiliser l'injection de dépendance pour injecter le CurrentUserId dans le Contrôleur ctor.
OriginalL'auteur Linkgoron
Dans le cas où vous "lancer le site" je soupçonne qu'il appelle le constructeur par défaut de votre contrôleur HomeController qui appellera à son tour la base du contrôleur de correpsonding ctor.
Essayez de modifier vos personnalisée ctor de public HomeController(IUnitOfWork unitOfWork) à
public HomeController(IUnitOfWork unitOfWork):base()
Ce sera assurez-vous d'appeler le contrôleur de base par défaut de ctor chaque fois qu'il est appelé.
HomeController
. Le seul constructeur est celui qui prend unIUnitOfWork
. Vous ne pouvez pas appelernew HomeController()
OriginalL'auteur Pepto