Si j'ai un contrôleur comme celui-ci :
[HttpPost]
public JsonResult FindStuff(string query)
{
var results = _repo.GetStuff(query);
var jsonResult = results.Select(x => new
{
id = x.Id,
name = x.Foo,
type = x.Bar
}).ToList();
return Json(jsonResult);
}
En gros, je récupère des éléments de mon référentiel, puis je les projette dans un fichier List<T>
de types anonymes.
Comment puis-je faire un test unitaire ?
System.Web.Mvc.JsonResult
a une propriété appelée Data
mais il est de type object
comme nous le pensions.
Cela signifie-t-il que si je veux tester que l'objet JSON possède les propriétés que j'attends ("id", "name", "type"), je dois utiliser la réflexion ?
EDIT :
Voici mon test :
// Arrange.
const string autoCompleteQuery = "soho";
// Act.
var actionResult = _controller.FindLocations(autoCompleteQuery);
// Assert.
Assert.IsNotNull(actionResult, "No ActionResult returned from action method.");
dynamic jsonCollection = actionResult.Data;
foreach (dynamic json in jsonCollection)
{
Assert.IsNotNull(json.id,
"JSON record does not contain \"id\" required property.");
Assert.IsNotNull(json.name,
"JSON record does not contain \"name\" required property.");
Assert.IsNotNull(json.type,
"JSON record does not contain \"type\" required property.");
}
Mais j'obtiens une erreur d'exécution dans la boucle, indiquant "object does not contain a definition for id".
Quand je fais un point d'arrêt, actionResult.Data
est défini comme un List<T>
de types anonymes, donc je me dis que si je les énumère, je peux vérifier les propriétés. Dans la boucle, l'objet fait ont une propriété appelée "id" - donc je ne suis pas sûr de la nature du problème.
0 votes
Concernant la modification, vous pouvez essayer quelque chose comme var items = (IEnumerable)actionResult.Data ; foreach(dynamic obj in items) {...}
1 votes
J'ai testé ici avec ` var list = (IList)data ; Assert.AreEqual(list.Count, 2) ; dynamic obj = data[0] ; Assert.AreEqual(obj.id, 12) ; Assert.AreEqual(obj.name, "Fred") ; Assert.AreEqual(obj.type, 'a') ; obj = data[1] ; Assert. AreEqual(obj.id,14) ; Assert.AreEqual(obj.name, "Jim") ; Assert.AreEqual(obj.type, 'c') ; foreach (dynamic d in list) { if (d.id == null) throw new InvalidOperationException() ; }` et ça semblait bien...
0 votes
Je vais essayer ce code demain quand je serai au bureau. merci.
0 votes
@Marc Gravell - êtes-vous sûr d'avoir essayé ? J'ai copié et collé exactement le code ci-dessus, et ça n'a pas marché. Premièrement,
data
est unobject
Il ne dispose donc pas d'un indexeur (data[0]
donne une erreur de syntaxe). corrigez-moi si j'ai tort, mais tout celadynamic
fait est de donner une liaison tardive au type, tout ce que nous faisons ici est de couler unobject
à unIList<object>
Je pense que je vais devoir désérialiser l'objet.0 votes
@rpm1984 veuillez noter le casting vers IList
0 votes
@Marc - j'ai fait un casting vers IList. Mais comme je l'ai dit plus haut, c'est une collection d'objets, donc l'erreur demeure.
1 votes
@RPM1984 quand il a été récupéré dans
obj
,obj
esdynamic
- donc la liaison tardive par article se produit toujours.0 votes
@Marc Gravell - Bon, je n'ai pas trop utilisé dynamic, mais comme je l'ai dit, je n'arrive pas à faire fonctionner votre solution, et @Matt Greer non plus. J'ai donc opté pour son approche basée sur la réflexion.
1 votes
@RPM - pas de problème, je suis juste content que vous ayez trouvé une solution qui fonctionne.
0 votes
@Marc - j'apprécie également votre aide :)