2011-10-01 27 views
5

Tôi đã cô lập các kiểm tra NUnit cho ứng dụng C# của tôi trong một hội đồng có tên là Tests.dll. Tệp cấu hình liên quan được gọi là Tests.dll.config. Đây là những gì Nunit sử dụng chứ không phải là tệp cấu hình thực tế của ứng dụng của tôi. Có vẻ như thế này (chỉ hiển thị một vài tùy chọn cấu hình có nhiều hơn nữa):Thao tác tệp app.config cho các bài kiểm tra đơn vị

<?xml version="1.0" encoding="utf-8"?> 

<configuration> 
    <appSettings> 
    <add key="useHostsFile" value="true" /> 
    <add key="importFile" value="true" /> 

    </appSettings> 
</configuration> 

Để đảm bảo ứng dụng của tôi được kiểm tra kỹ lưỡng, tôi sẽ cần thay đổi tùy chọn cấu hình giữa các thử nghiệm. Sau khi tôi đã chạy một vài thử nghiệm, tôi muốn thêm một số giá trị cấu hình mới vào tệp và có các giá trị này được sử dụng bởi các thử nghiệm tiếp theo. Tôi cần thêm mã nào để làm điều này?

+0

Bạn có thể giải thích trường hợp sử dụng tốt hơn không? Tại sao bạn cần phải thay đổi tests.dll.config trong thời gian chạy? –

+1

Đây chính là câu hỏi giống như câu hỏi này: http://stackoverflow.com/questions/168931/unit-testing-the-app-config-file-with-nunit –

+0

OK, tôi đoán nó có thể được đóng lại. Cảm ơn con trỏ. – FunLovinCoder

Trả lời

3

Tôi khuyên bạn nên triển khai giao diện IConfig với các thuộc tính sử dụngHostsFile và importFile. Sau đó, tôi sẽ loại bỏ tất cả các phụ thuộc trực tiếp vào tập tin này ngoại trừ trong Class ConfigDefault mà thực hiện IConfig. Trong triển khai này, bạn tải tệp cấu hình bình thường của mình. Đối với mỗi bài kiểm tra, bạn có thể thực hiện một Lớp khác cũng thừa kế từ IConfig. Tôi đề nghị sử dụng Dependecy Injection. Ninject miễn phí và dễ sử dụng.

0

tôi sử dụng mã này:

[TestMethod] 
    public void Test_general() 
    { 
     var cs = new ConnectionStringSettings(); 
     cs.Name = "ConnectionStrings.Oracle"; 
     cs.ConnectionString = "DATA SOURCE=xxx;PASSWORD=xxx;PERSIST SECURITY INFO=True;USER ID=xxx"; 
     cs.ProviderName = "Oracle.DataAccess.Client"; 

     var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
     //config.ConnectionStrings.ConnectionStrings.Clear(); 
     config.ConnectionStrings.ConnectionStrings.Remove(cs.Name); 
     config.ConnectionStrings.ConnectionStrings.Add(cs); 
     config.Save(ConfigurationSaveMode.Modified); 
     ConfigurationManager.RefreshSection("connectionStrings"); 

     // your code for your test here 
    } 
0

Dưới đây là hai của tôi cent để thách thức này. Đơn giản, tạo một lớp AppSettings mới như là một lớp trừu tượng. Trong các hoạt động bình thường, nó sẽ chỉ đọc các cài đặt từ tệp cấu hình ứng dụng. Nhưng các bài kiểm tra đơn vị có thể ghi đè lên các thiết lập trên cơ sở mỗi thread cho phép các bài kiểm tra đơn vị thực thi song song với các thiết lập khác nhau.

internal sealed class AppSettings 
{ 
    private static readonly AppSettings instance; 
    private static ConcurrentDictionary<int, AppSettings> threadInstances; 
    private string _setting1; 
    private string _setting2; 

    static AppSettings() { instance = new AppSettings(); } 

    internal AppSettings(string setting1 = null, string setting2 = null) { 
     _setting1 = setting1 != null ? setting1 : Properties.Settings.Default.Setting1; 
     _setting2 = setting2 != null ? setting2 : Properties.Settings.Default.Setting2; 
    } 

    internal static AppSettings Instance { 
     get { 
      if (threadInstances != null) { 
       AppSettings threadInstance; 
       if (threadedInstances.TryGetValue(Thread.CurrentThread.ManagedThreadId, out threadInstance)) { 
        return threadInstance; 
       } 
      } 
      return instance; 
     } 

     set { 
      if (threadInstances == null) { 
       lock (instance) { 
        if (threadInstances == null) { 
         int numProcs = Environment.ProcessorCount; 
         int concurrencyLevel = numProcs * 2; 
         threadInstances = new ConcurrentDictionary<int, AppSettings>(concurrencyLevel, 5); 
        } 
       } 
      } 

      if (value != null) { 
       threadInstances.AddOrUpdate(Thread.CurrentThread.ManagedThreadId, value, (key, oldValue) => value); 
      } else { 
       AppSettings threadInstance; 
       threadInstances.TryRemove(Thread.CurrentThread.ManagedThreadId, out threadInstance); 
      } 
     } 
    } 

    internal static string Setting1 => Instance._setting1; 

    internal static string Setting2 => Instance._setting2; 
} 

Trong mã ứng dụng, cài đặt truy cập bằng cách sử dụng thuộc tính tĩnh:

function void MyApplicationMethod() { 
    string setting1 = AppSettings.Setting1; 
    string setting2 = AppSettings.Setting2; 
} 

Trong các thử nghiệm đơn vị, cài đặt tùy chọn ghi đè chọn:

[TestClass] 
public class MyUnitTest 
{ 
    [TestCleanup] 
    public void CleanupTest() 
    { 
     // 
     // Clear any app settings that were applied for the current test runner thread. 
     // 
     AppSettings.Instance = null; 
    } 

    [TestMethod] 
    public void MyUnitMethod() 
    { 
     AppSettings.Instance = new AppSettings(setting1: "New settings value for current thread"); 
     // Your test code goes here 
    } 
} 

LƯU Ý: Như tất cả các phương pháp của AppSettings lớp được khai báo là nội bộ, nó là cần thiết để làm cho chúng có thể nhìn thấy được với assembly thử nghiệm đơn vị bằng cách sử dụng thuộc tính: [assembly: InternalsVisibleTo ("< tên lắp ráp >, PublicKey = < khóa công khai > ")]

Các vấn đề liên quan