Я застрял в этой точке кода, что не знаю, как насмехаться:
ConfigurationManager.AppSettings["User"];
Мне нужно высмеять ConfigurationManager, но у меня нет подсказки, я использую Moq.
Кто-нибудь может дать мне совет? Спасибо!
Я застрял в этой точке кода, что не знаю, как насмехаться:
ConfigurationManager.AppSettings["User"];
Мне нужно высмеять ConfigurationManager, но у меня нет подсказки, я использую Moq.
Кто-нибудь может дать мне совет? Спасибо!
Я считаю, что один стандартный подход к этому заключается в использовании шаблона фасада для переноса менеджера конфигурации, а затем у вас есть что-то слабо связанное с тем, что вы контролируете.
Итак, вы бы обернули ConfigurationManager. Что-то вроде:
public class Configuration: IConfiguration
{
public User
{
get{
return ConfigurationManager.AppSettings["User"];
}
}
}
(Вы можете просто извлечь интерфейс из своего класса конфигурации, а затем использовать этот интерфейс повсюду в своем коде) Тогда вы просто издеваетесь над IConfiguration. Возможно, вы сможете реализовать сам фасад несколькими способами. Выше я решил просто обернуть отдельные свойства. Вы также получаете преимущество, заключающееся в том, чтобы иметь строго типизированную информацию для работы с, а не слабо типизированными массивами хешей.
Я использую AspnetMvc4. Момент назад я написал
ConfigurationManager.AppSettings["mykey"] = "myvalue";
в моем тестовом методе, и он отлично работал.
Объяснение: метод тестирования выполняется в контексте с настройками приложения, взятыми из, как правило, web.config
или myapp.config
. ConfigurationsManager
может достичь этого глобального объекта-приложения и управлять им.
Хотя: Если у вас параллельно работает тестовый бегун, это не очень хорошая идея.
Возможно, это не то, что вам нужно выполнить, но считаете ли вы, что используете приложение app.config в своем тестовом проекте? Таким образом, ConfigurationManager получит значения, которые вы добавили в app.config, и вам не нужно ничего издеваться. Это решение работает хорошо для моих нужд, потому что мне никогда не нужно тестировать "переменный" файл конфигурации.
Вы можете использовать прокладки, чтобы изменить 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. Надеюсь это поможет.
Вы считали, что вместо того, чтобы насмехаться? Свойством 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, пока вам это не понадобится.
Это статическое свойство, а Moq предназначено для методов или классов экземпляра Moq, которые можно издеваться через наследование. Другими словами, Moq не поможет вам здесь.
Для насмешливой статики я использую инструмент Moles, который является бесплатным. Существуют и другие средства выделения изоляции, такие как Typemock, которые тоже могут это сделать, хотя я считаю, что это платные инструменты.
Когда речь заходит о статике и тестировании, другой вариант заключается в том, чтобы создать статическое состояние самостоятельно, хотя это часто может быть проблематичным (так как я бы предположил, что это будет в вашем случае).
И, наконец, если рамки изоляции не являются опцией, и вы привержены этому подходу, фасад, упомянутый Джошуа, - это хороший подход или любой подход в целом, когда вы ставите код клиента из этого бизнеса логику, которую вы используете для тестирования.
Я думаю, что написать собственный поставщик 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; } }
}