Yanıtlar:
Buna standart bir yaklaşımın , konfigürasyon yöneticisini sarmak için bir cephe modeli kullanmak olduğuna inanıyorum ve daha sonra üzerinde kontrol sahibi olduğunuz gevşek bir şekilde bağlanmış bir şeye sahipsiniz.
Böylece ConfigurationManager'ı sarmalayabilirsiniz. Gibi bir şey:
public class Configuration: IConfiguration
{
public User
{
get
{
return ConfigurationManager.AppSettings["User"];
}
}
}
(Yapılandırma sınıfınızdan bir arabirim çıkarabilir ve ardından bu arabirimi kodunuzun her yerinde kullanabilirsiniz) Ardından, IConfiguration ile dalga geçersiniz. Cephenin kendisini birkaç farklı şekilde uygulayabilirsiniz. Yukarıda sadece bireysel mülkleri sarmayı seçtim. Ayrıca, zayıf yazılmış karma diziler yerine çalışmak için güçlü bir şekilde yazılmış bilgilere sahip olmanın yan avantajını da elde edersiniz.
var configurationMock = new Mock<IConfiguration>();
ve kurulum için:configurationMock.SetupGet(s => s.User).Returns("This is what the user property returns!");
AspnetMvc4 kullanıyorum. Bir dakika önce yazdım
ConfigurationManager.AppSettings["mykey"] = "myvalue";
benim test yöntemimde ve mükemmel çalıştı.
Açıklama: Test yöntemi, tipik olarak a web.config
veya myapp.config
. ConfigurationsManager
bu uygulama genel nesnesine ulaşabilir ve onu işleyebilir.
Yine de: Testleri paralel olarak çalıştıran bir test çalıştırıcınız varsa, bu iyi bir fikir değildir.
ConfigurationManager.AppSettings
Bir olduğunu NameValueCollection
parçacığı için güvenli değil, hangi uygun senkronizasyon bırakmadan kullanmayı o kadar paralel testler zaten iyi bir fikir değildir. Aksi takdirde sadece çağırabilir ConfigurationManager.AppSettings.Clear()
senin içinde TestInitialize
sen altın / ctor ve.
Belki başarmanız gereken şey bu değildir, ancak test projenizde bir app.config kullanmayı düşündünüz mü? Böylece ConfigurationManager, app.config dosyasına koyduğunuz değerleri alır ve hiçbir şeyle alay etmenize gerek kalmaz. Bu çözüm ihtiyaçlarım için iyi çalışıyor çünkü "değişken" bir yapılandırma dosyasını asla test etmem gerekmiyor.
Web.config
, projeyi çevreleyen kısımdan çekilir . Test sırasında, iyi bilinen bazı değerleri almak app.config
çok geçerlidir. Birim testi, "cluster1" i çektiği zaman koşulların çalıştığından emin olmalıdır; bu durumda sadece 4 farklı küme vardır.
AppSettings
Özel bir NameValueCollection
nesneye değiştirmek için şimler kullanabilirsiniz . İşte bunu nasıl başarabileceğinize dair bir örnek:
[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 Fakes ile Test Altında İzole Etme Kodu sayfasında şimler ve sahte ürünler hakkında daha fazla bilgi edinebilirsiniz . Bu yardımcı olur umarım.
Alay etmek yerine saplamayı düşündün mü? AppSettings
Tesiste olduğu 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...
}
}
Faydaları, daha basit bir uygulama ve gerçekten ihtiyacınız olana kadar System.Configuration'a bağımlılık olmamasıdır.
IConfiguration
Joshua Enfield'in önerdiği gibi bir ile sarmak çok yüksek düzeyde olabilir ve kötü yapılandırma değeri ayrıştırma gibi şeyler nedeniyle var olan hataları gözden kaçırabilirsiniz. Öte yandan, ConfigurationManager.AppSettings
LosManos'un önerdiği gibi doğrudan kullanmak çok fazla bir uygulama ayrıntısıdır, diğer testler üzerinde yan etkilere sahip olabileceğinden ve manuel senkronizasyon olmadan paralel test çalışmalarında kullanılamayacağından bahsetmiyorum bile ( NameValueConnection
iş parçacığı güvenli değildir).
Bu statik bir özelliktir ve Moq, miras yoluyla alay edilebilen Moq örnek yöntemleri veya sınıfları için tasarlanmıştır. Başka bir deyişle, Moq burada size herhangi bir yardımcı olmayacak.
Statiği alay etmek için , ücretsiz olan Moles adlı bir araç kullanıyorum . Typemock gibi bunu yapabilen başka çerçeve izolasyon araçları da var, ancak bunların ücretli araçlar olduğuna inanıyorum.
Statik ve test söz konusu olduğunda, başka bir seçenek de statik durumu kendiniz oluşturmaktır, ancak bu genellikle sorunlu olabilir (sizin durumunuzda olacağını tahmin ediyorum).
Ve son olarak, izolasyon çerçeveleri bir seçenek değilse ve bu yaklaşıma bağlıysanız, Joshua'nın bahsettiği dış görünüş iyi bir yaklaşımdır veya genel olarak bunun müşteri kodunu hesaba kattığınız iş mantığından uzak tuttuğunuz herhangi bir yaklaşımdır. test etmek için kullanıyoruz.
Kendi app.config sağlayıcınızı yazmak basit bir iştir ve diğer her şeyden daha yararlıdır. Özellikle şim vb. Sahtekarlıklardan kaçınmalısınız çünkü bunları kullandığınız anda Düzenle ve Devam Et çalışmıyor.
Kullandığım sağlayıcılar şuna benziyor:
Varsayılan olarak değerleri 'den alırlar, App.config
ancak birim testleri için tüm değerleri geçersiz kılabilir ve her testte bağımsız olarak kullanabilirim.
Herhangi bir arayüze veya her defasında tekrar tekrar uygulamaya gerek yoktur. Bir yardımcı program dll var ve bu küçük yardımcıyı birçok proje ve birim testinde kullanıyorum.
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; } }
}
İhtiyacınız olanı ayarlamaya ne dersiniz? Çünkü .NET ile dalga geçmek istemiyorum, değil mi ...?
System.Configuration.ConfigurationManager.AppSettings["myKey"] = "myVal";
Uygulamanın yalnızca istediğiniz şeyi gördüğünden emin olmak için muhtemelen Uygulama Ayarları'nı önceden temizlemelisiniz.