2016-10-17 10 views
1

私はそれに続く関数を持ち、古いプロジェクトに単体テストを追加しようとしています。 Iユニットテストでは初心者だ質問は愚かである場合ので、私を許して...ファイルを読み取る静的関数の単体テスト

public static string GetDefaultName(bool isResponsive) 
    { 
     //Read web.config file 
     Configuration configuration = WebConfigurationManager.OpenWebConfiguration(System.Web.HttpContext.Current.Request.ApplicationPath); 
     if (!isResponsive) 
     { 
      if (configuration.AppSettings.Settings.AllKeys.Contains("defaultTheme")) 
      { 
       return configuration.AppSettings.Settings["defaultTheme"].Value; 
      } 
      else 
       return "default"; 
     } 
     else 
     { 
      // ... 
     } 
    } 

そして私は、このようにユニットテストを書くことをしようとしている:

[TestMethod] 
    public void ReturnDefaulThemeNametIfThemeIsResponsive() 
    { 
     var theme = new Theme {isResponsive = true}; 

     var defaultName = Themes.GetDefaultName(theme.isResponsive); 
     Assert.AreEqual(defaultName, "defaultThemeResponsive"); 
    } 

私が何を疑問に思いますこの静的関数をテストする最良の方法であり、web.configファイルを読んだ部分を模擬する方法は?

+1

現在、あなた自身のアクセスはメソッド自体の中で起こるので、 'web.config'の読み物をモックすることはできません。このメソッドをリファクタリングして依存関係をパラメータとして取り入れることを検討します。その後、あなたはそれらをモックすることができます。あなたができる唯一のことは、ユニットテストプロジェクトの 'app.config'ファイルを更新することですが、テストの設定サブシステムを実際にテストしています(これは、すべての目的と目的がアプリケーションの設定サブシステム)。 –

答えて

1

(コンパイルされませんが、あなたのアイデアを得るでしょう)。しかし、この場合は可能です。リファクタリングをしなくてはなりません。

まず、設定にアクセスするためのすべての呼び出しを抽象化する必要があります。

public interface IThemeSettings { 
    bool Contains(string key); 
    string this[string key] { get; } 
} 

その後、依存関係として、この抽象化を使用するために、静的なテーマのユーティリティクラスを更新することができ

[TestMethod] 
public void ReturnDefaulThemeNametIfThemeIsResponsive() { 
    //Arrange 
    var key = "defaultTheme"; 
    var expected = "defaultThemeResponsive"; 

    var mockSettings = new Mock<IThemeSettings>(); 
    mockSettings.Setup(m => m.Contains(key)).Returns(true); 
    mockSettings.Setup(m => m[key]).Returns(expected); 

    //In production you would also do something like this with 
    //the actual production implementation, not a mock 
    Themes.Configure(() => mockSettings.Object); 

    var theme = new Theme { isResponsive = true }; 

    //Act 
    var defaultName = Themes.GetDefaultName(theme.isResponsive); 

    //Assert 
    Assert.AreEqual(expected, defaultName); 
} 

をテストするとき、あなたが今、モックを使用するユーティリティを設定することができますWAT

public static class Themes { 
    private static IThemeSettings themes; 

    public static void Configure(Func<IThemeSettings> factory) { 
     if (factory == null) throw new InvalidOperationException("Must provide a valid factory method"); 
     themes = factory(); 
    } 

    public static string GetDefaultName(bool isResponsive) { 
     if (themes == null) throw new InvalidOperationException("Themes has not been configured."); 
     string result = string.Empty; 
     if (!isResponsive) { 
      if (themes.Contains("defaultTheme")) { 
       result = themes["defaultTheme"]; 
      } else 
       result = "default"; 
     } else { 
      // ... 
     } 
     return result; 
    } 

    //... 
} 

この場合、私はモックフレームワークとしてMoqを使用しました。

いくつかのアドバイス。あなたのクラスをHttpContextに密接に結合させないようにしてください。あなたの授業は、抽象的なものであり、具体的なものではありません。

1

あなたの方法は現時点で設計されているので、設定ファイルを読み込んでいる部分をモックすることはできません。あなたがそれを行うことができるようにしたいなら、それをあなたのメソッドへのパラメータにする必要があります。それを容易にする一つの方法は、その後、これを実装して設定マネージャクラスでConfigurationオブジェクトをラップ

public interface ISetting 
{ 
    string GetConfigItem(string itemName); 
} 

のようなインタフェースを定義することです。

public class MySettings:ISetting 
{ 
    public string GetConfigItem(string ItemName) 
    { 
     // return value of the setting. In your case code that gets value of "defaultTheme" 
    } 
} 

あなたのメソッドはISettingに依存するようになりました。あなたがインターフェイスを実装モックを作成することができ、これまであなたは今ユニットテストを作成することができます。これにより、現在の状態とweb.config

public class SettingsTestHelper:ISetting 
{ 
    private _valueToReturn; 
    public SettingsTestHelper(string valueToReturn) 
    { 
     _valueToReturn=valueToReturn; 
    } 
    public string GetConfigItem(string itemName) 
    { 
     return valueToReturn; 
    } 
} 

の内容とは無関係に必要な値何戻りますテスト目的のために

私は、彼らはユニットテストが困難であるとして依存している静的なユーティリティから離れて滞在してみてください

[TestMethod] 
public void CanGetSetting() 
{ 
    var helper = new SettingsTestHelper("default"); 
    var result = ClasThatImplementsYourStaticMethod.GetDefaultName(helper, true); 
    Assert.AreEqual(expected, actual); 
} 
関連する問題