Question

Je suis en train de parcourir l'excellent message de Scott Guthrie sur Bêta 1 d'ASP.NET MVC . Il y présente les améliorations apportées à la méthode UpdateModel et comment elles améliorent les tests unitaires. J'ai recréé un projet similaire, mais chaque fois que j'exécute un UnitTest contenant un appel à UpdateModel, je reçois une ArgumentNullException nommant le paramètre controllerContext.

Voici les éléments pertinents, en commençant par mon modèle:

public class Country {
  public Int32 ID { get; set; }
  public String Name { get; set; }
  public String Iso3166 { get; set; }
}

L'action du contrôleur:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Int32 id, FormCollection form)
{
  using ( ModelBindingDataContext db = new ModelBindingDataContext() ) {
    Country country = db.Countries.Where(c => c.CountryID == id).SingleOrDefault();

    try {
      UpdateModel(country, form);

      db.SubmitChanges();

      return RedirectToAction("Index");
    }
    catch {
      return View(country);
    }
  }
}

Et enfin mon test unitaire qui échoue:

[TestMethod]
public void Edit()
{
  CountryController controller = new CountryController();
  FormCollection form = new FormCollection();
  form.Add("Name", "Canada");
  form.Add("Iso3166", "CA");

  var result = controller.Edit(2 /*Canada*/, form) as RedirectToRouteResult;

  Assert.IsNotNull(result, "Expected to be redirected on successful POST.");
  Assert.AreEqual("Show", result.RouteName, "Expected to redirect to the View action.");
}

ArgumentNullException est levé par l'appel de UpdateModel avec le message "La valeur ne peut pas être null. Nom du paramètre: controllerContext " ;. Je suppose que quelque part le UpdateModel nécessite le System.Web.Mvc.ControllerContext qui n'est pas présent lors de l'exécution du test.

Je suppose également que je fais quelque chose de mal quelque part et que je dois juste indiquer la direction à suivre.

Aide s'il vous plaît!

Était-ce utile?

La solution

Je ne pense pas que cela puisse être fait car TryUpdateModel, utilisé par UpdateModel, fait référence au ControllerContext, qui est null lorsqu'il est appelé à partir d'un test unitaire. J'utilise RhinoMocks pour simuler ou remplacer les divers composants nécessaires au contrôleur.

var routeData = new RouteData();
var httpContext = MockRepository.GenerateStub<HttpContextBase>();
FormCollection formParameters = new FormCollection();

EventController controller = new EventController();
ControllerContext controllerContext = 
    MockRepository.GenerateStub<ControllerContext>( httpContext,
                                                    routeData,
                                                    controller );
controller.ControllerContext = controllerContext;

ViewResult result = controller.Create( formParameters ) as ViewResult;

Assert.AreEqual( "Event", result.Values["controller"] );
Assert.AreEqual( "Show", result.Values["action"] );
Assert.AreEqual( 0, result.Values["id"] );

Voici le bit pertinent de la source Controller.cs sur www.codeplex.com/aspnet:

protected internal bool TryUpdateModel<TModel>( ... ) where TModel : class
{

     ....

    ModelBindingContext bindingContext =
           new ModelBindingContext( ControllerContext,
                                    valueProvider,
                                    typeof(TModel),
                                    prefix,
                                    () => model,
                                    ModelState,
                                    propertyFilter );

     ...
}

Autres conseils

J'avais le même problème. Après avoir lu la solution de tvanfosson, j’ai essayé une solution simple ne faisant pas appel à un framework factice.

Ajoutez un ControllerContext par défaut au contrôleur comme suit:

CountryController controller = new CountryController();
controller.ControllerContext = new ControllerContext();

Cela a permis de supprimer l'erreur, ce qui me convenait parfaitement lors des tests unitaires. J'espère que cela pourra aider quelqu'un d'autre.

Vous pouvez également créer un proxy de données de formulaire, comme

.
public class CountryEdit {
  public String Name { get; set; }
  public String Iso3166 { get; set; }
}
  • Plus. Créez facilement des tests unitaires
  • Plus. Définir la mise à jour de la liste blanche des champs à partir de la publication
  • Plus. Règles de validation pour une installation facile, testez-le facilement.
  • Moins. Vous devez déplacer la date du proxy sur votre modèle

Alors Controller.Action devrait ressembler à

public ActionResult Edit(Int32 id, CountryEdit input)
{
  var Country = input.ToDb();
  // Continue your code
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top