Как обмануть ConfigurationManager.AppSettings с moq
Я застрял в этой точке кода, что не знаю, как насмехаться:
ConfigurationManager.AppSettings["User"];
Мне нужно высмеять ConfigurationManager, но у меня нет подсказки, я использую Moq.
Кто-нибудь может дать мне совет? Спасибо!
Ответы
Ответ 1
Я считаю, что один стандартный подход к этому заключается в использовании шаблона фасада для переноса менеджера конфигурации, а затем у вас есть что-то слабо связанное с тем, что вы контролируете.
Итак, вы бы обернули ConfigurationManager. Что-то вроде:
public class Configuration: IConfiguration
{
public User
{
get{
return ConfigurationManager.AppSettings["User"];
}
}
}
(Вы можете просто извлечь интерфейс из своего класса конфигурации, а затем использовать этот интерфейс повсюду в своем коде)
Тогда вы просто издеваетесь над IConfiguration. Возможно, вы сможете реализовать сам фасад несколькими способами. Выше я решил просто обернуть отдельные свойства. Вы также получаете преимущество, заключающееся в том, чтобы иметь строго типизированную информацию для работы с, а не слабо типизированными массивами хешей.
Ответ 2
Я использую AspnetMvc4. Момент назад я написал
ConfigurationManager.AppSettings["mykey"] = "myvalue";
в моем тестовом методе, и он отлично работал.
Объяснение: метод тестирования выполняется в контексте с настройками приложения, взятыми из, как правило, web.config
или myapp.config
. ConfigurationsManager
может достичь этого глобального объекта-приложения и управлять им.
Хотя: Если у вас параллельно работает тестовый бегун, это не очень хорошая идея.
Ответ 3
Возможно, это не то, что вам нужно выполнить, но считаете ли вы, что используете приложение app.config в своем тестовом проекте?
Таким образом, ConfigurationManager получит значения, которые вы добавили в app.config, и вам не нужно ничего издеваться.
Это решение работает хорошо для моих нужд, потому что мне никогда не нужно тестировать "переменный" файл конфигурации.
Ответ 4
Вы можете использовать прокладки, чтобы изменить AppSettings
на пользовательский объект NameValueCollection
. Вот пример того, как вы можете это сделать:
[TestMethod]
public void TestSomething()
{
using(ShimsContext.Create()) {
const string key = "key";
const string value = "value";
ShimConfigurationManager.AppSettingsGet = () =>
{
NameValueCollection nameValueCollection = new NameValueCollection();
nameValueCollection.Add(key, value);
return nameValueCollection;
};
///
// Test code here.
///
// Validation code goes here.
}
}
Вы можете больше узнать о прокладках и подделках, Изолировать код под тестом с подделками Microsoft. Надеюсь это поможет.
Ответ 5
Вы считали, что вместо того, чтобы насмехаться? Свойством AppSettings
является 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
string user = _settings["User"];
// log
Trace.TraceInformation("User = \"{0}\"", user);
// do something else...
}
}
Преимущества - это более простая реализация и отсутствие зависимости от System.Configuration, пока вам это не понадобится.
Ответ 6
Это статическое свойство, а Moq предназначено для методов или классов экземпляра Moq, которые можно издеваться через наследование. Другими словами, Moq не поможет вам здесь.
Для насмешливой статики я использую инструмент Moles, который является бесплатным. Существуют и другие средства выделения изоляции, такие как Typemock, которые тоже могут это сделать, хотя я считаю, что это платные инструменты.
Когда речь заходит о статике и тестировании, другой вариант заключается в том, чтобы создать статическое состояние самостоятельно, хотя это часто может быть проблематичным (так как я бы предположил, что это будет в вашем случае).
И, наконец, если рамки изоляции не являются опцией, и вы привержены этому подходу, фасад, упомянутый Джошуа, - это хороший подход или любой подход в целом, когда вы ставите код клиента из этого бизнеса логику, которую вы используете для тестирования.
Ответ 7
Я думаю, что написать собственный поставщик app.config - простая задача и более полезная, чем что-либо еще. Особенно вам следует избегать любых подделок, таких как прокладки и т.д., Потому что, как только вы их используете, Edit и Continue больше не работают.
Поставщики, которые я использую, выглядят следующим образом:
По умолчанию они получают значения из App.config
, но для модульных тестов я могу переопределить все значения и использовать их в каждом тесте самостоятельно.
Нет необходимости в каких-либо интерфейсах или реализовывать его каждый раз снова и снова. У меня есть утилита dll и использую этот небольшой помощник во многих проектах и модульных тестах.
public class AppConfigProvider
{
public AppConfigProvider()
{
ConnectionStrings = new ConnectionStringsProvider();
AppSettings = new AppSettingsProvider();
}
public ConnectionStringsProvider ConnectionStrings { get; private set; }
public AppSettingsProvider AppSettings { get; private set; }
}
public class ConnectionStringsProvider
{
private readonly Dictionary<string, string> _customValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public string this[string key]
{
get
{
string customValue;
if (_customValues.TryGetValue(key, out customValue))
{
return customValue;
}
var connectionStringSettings = ConfigurationManager.ConnectionStrings[key];
return connectionStringSettings == null ? null : connectionStringSettings.ConnectionString;
}
}
public Dictionary<string, string> CustomValues { get { return _customValues; } }
}
public class AppSettingsProvider
{
private readonly Dictionary<string, string> _customValues = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public string this[string key]
{
get
{
string customValue;
return _customValues.TryGetValue(key, out customValue) ? customValue : ConfigurationManager.AppSettings[key];
}
}
public Dictionary<string, string> CustomValues { get { return _customValues; } }
}