Les autres réponses ont déjà montré comment vous pouvez vous moquer d'une chaîne de propriété pour contourner votre problème.
Mais le vrai problème ici est que les tests unitaires et les moqueurs ne fonctionnent pas vraiment bien si vous ne respectez pas le law of demeter. Si vous voulez que votre code soit testable et réutilisable au maximum, vous devez injecter directement les dépendances réelles de votre code et cacher ces dépendances derrière les abstractions.
Par exemple, au lieu de le faire:
public class MyClass
{
public ControllerContext Context { get; set; }
public void DoSomething()
{
// BAD: we're only interested in the name, but instead we've injected
// a ControllerContext that can give us a HttpContext that can give us
// a User that can give us an Identity that can give us the Name.
string name = Context.HttpContext.User.Identity.Name;
// etcetera
}
}
Faites ceci:
public class MyClass
{
public INameProvider NameProvider { get; set; }
public void DoSomething()
{
// GOOD: we've injected a name provider
string name = NameProvider.Name;
// etcetera
}
}
En introduisant le concept INameProvider
, votre code de composants, tests et simulacres deviennent beaucoup plus simples. Votre code devient également plus réutilisable: il ne dépend que du concept abstrait d'un "fournisseur de nom", plutôt que d'un tas de classes ASP.NET. Vous serez en mesure de réutiliser votre composant dans n'importe quel environnement tant qu'il est possible d'implémenter un adaptateur INameProvider
. Le compromis est que vous aurez besoin de déclarer l'interface INameProvider
et d'écrire une classe wrapper qui l'implémente. Lorsque vous suivez systématiquement cette approche, vous vous retrouverez avec de nombreuses petites interfaces et classes d'adaptateurs. Telle est la voie du développement piloté par les tests.
(Si vous vous demandez pourquoi j'introduis INameProvider
au lieu de définir le nom directement - c'est pour que le conteneur IoC puisse utiliser l'interface pour faire correspondre la dépendance avec l'implémentation.
Cela a bien fonctionné. Toujours dû mettre un objet dans la propriété 'HttpContext.User' mais cela a été facilement accompli en faisant:' HttpContext.User = new GenericPrincipal (new GenericIdentity (loginName), null); ' – ahsteele