Comment simuler ConfigurationManager.AppSettings avec moq

Je suis coincé à ce sharepoint code que je ne sais pas comment me moquer:

ConfigurationManager.AppSettings["User"]; 

Je dois me moquer du ConfigurationManager, mais je n’ai pas la moindre idée, j’utilise Moq .

Quelqu’un peut me donner un conseil? Merci!

Je pense qu’une approche standard consiste à utiliser un motif de façade pour envelopper le gestionnaire de configuration et que vous ayez quelque chose de vaguement couplé sur lequel vous avez le contrôle.

Donc, vous emballeriez le ConfigurationManager. Quelque chose comme:

 public class Configuration: IConfiguration { public User { get{ return ConfigurationManager.AppSettings["User"]; } } } 

(Vous pouvez simplement extraire une interface de votre classe de configuration, puis utiliser cette interface partout dans votre code) Ensuite, il vous suffit de simuler la configuration IConfigurée. Vous pourriez être en mesure de mettre en œuvre la façade elle-même de différentes manières. Ci-dessus, j’ai choisi de simplement envelopper les propriétés individuelles. Vous obtenez également l’avantage supplémentaire d’avoir des informations fortement typées pour travailler avec des tableaux de hachage faiblement typés.

J’utilise AspnetMvc4. Il y a un instant, j’ai écrit

 ConfigurationManager.AppSettings["mykey"] = "myvalue"; 

dans ma méthode de test et cela a parfaitement fonctionné.

Explication: la méthode de test s’exécute dans un contexte contenant des parameters d’application, généralement un web.config ou myapp.config . ConfigurationsManager peut atteindre cet object global d’application et le manipuler.

Cependant: Si vous avez un testeur qui exécute des tests en parallèle, ce n’est pas une bonne idée.

Peut-être n’est-ce pas ce que vous devez accomplir, mais avez-vous envisagé d’utiliser un app.config dans votre projet de test? Donc, le ConfigurationManager obtiendra les valeurs que vous avez mises dans app.config et vous n’avez pas besoin de vous moquer de quoi que ce soit. Cette solution fonctionne bien pour mes besoins, car je n’ai jamais besoin de tester un fichier de configuration “variable”.

Vous pouvez utiliser des shims pour modifier AppSettings en un object NameValueCollection personnalisé. Voici un exemple de la façon dont vous pouvez y parvenir:

 [TestMethod] public void TestSomething() { using(ShimsContext.Create()) { const ssortingng key = "key"; const ssortingng value = "value"; ShimConfigurationManager.AppSettingsGet = () => { NameValueCollection nameValueCollection = new NameValueCollection(); nameValueCollection.Add(key, value); return nameValueCollection; }; /// // Test code here. /// // Validation code goes here. } } 

Vous pouvez en savoir plus sur les cales et les contrefaçons sur, Isolating Code Under Test with Microsoft Fakes . J’espère que cela t’aides.

Avez-vous pensé à tailler au lieu de vous moquer? La propriété AppSettings est un NameValueCollection :

 [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { // Arrange var settings = new NameValueCollection {{"User", "Otuyh"}}; var classUnderTest = new ClassUnderTest(settings); // Act classUnderTest.MethodUnderTest(); // Assert something... } } public class ClassUnderTest { private readonly NameValueCollection _settings; public ClassUnderTest(NameValueCollection settings) { _settings = settings; } public void MethodUnderTest() { // get the User from Settings ssortingng user = _settings["User"]; // log Trace.TraceInformation("User = \"{0}\"", user); // do something else... } } 

Les avantages sont une implémentation plus simple et aucune dépendance à System.Configuration tant que vous n’en avez pas vraiment besoin.

C’est une propriété statique, et Moq est conçu pour les méthodes d’instance Moq ou les classes pouvant être reproduites via l’inheritance. En d’autres termes, Moq ne vous aidera pas ici.

Pour la statique moqueuse, j’utilise un outil appelé Moles , qui est gratuit. Il existe d’autres outils d’isolation de framework, comme Typemock, qui peuvent le faire aussi, même si je pense que ce sont des outils payants.

Pour ce qui est de la statique et des tests, une autre option consiste à créer vous-même l’état statique, même si cela peut souvent poser problème (j’imagine que ce serait le cas dans votre cas).

Et, enfin, si les frameworks d’isolation ne sont pas une option et que vous vous engagez dans cette approche, la façade mentionnée par Joshua est une bonne approche ou une approche en général qui éloigne le code client de la logique métier que vous utilise pour tester.

Je pense que l’écriture de votre propre fournisseur app.config est une tâche simple et plus utile que toute autre chose. En particulier, évitez les faux comme les cales, car dès que vous les utilisez, Edit & Continue ne fonctionne plus.

Les fournisseurs que j’utilise ressemblent à ceci:

Par défaut, ils obtiennent les valeurs de App.config mais pour les tests unitaires, je peux remplacer toutes les valeurs et les utiliser indépendamment dans chaque test.

Il n’y a pas besoin d’interfaces ou de l’implémenter à chaque fois encore et encore. J’ai une DLL utilitaire et utilise cette petite aide dans de nombreux projets et tests unitaires.

 public class AppConfigProvider { public AppConfigProvider() { ConnectionSsortingngs = new ConnectionSsortingngsProvider(); AppSettings = new AppSettingsProvider(); } public ConnectionSsortingngsProvider ConnectionSsortingngs { get; private set; } public AppSettingsProvider AppSettings { get; private set; } } public class ConnectionSsortingngsProvider { private readonly Dictionary _customValues = new Dictionary(SsortingngComparer.OrdinalIgnoreCase); public ssortingng this[ssortingng key] { get { ssortingng customValue; if (_customValues.TryGetValue(key, out customValue)) { return customValue; } var connectionSsortingngSettings = ConfigurationManager.ConnectionSsortingngs[key]; return connectionSsortingngSettings == null ? null : connectionSsortingngSettings.ConnectionSsortingng; } } public Dictionary CustomValues { get { return _customValues; } } } public class AppSettingsProvider { private readonly Dictionary _customValues = new Dictionary(SsortingngComparer.OrdinalIgnoreCase); public ssortingng this[ssortingng key] { get { ssortingng customValue; return _customValues.TryGetValue(key, out customValue) ? customValue : ConfigurationManager.AppSettings[key]; } } public Dictionary CustomValues { get { return _customValues; } } }