2012-03-02 7 views
10

現在、私は適切な単体テストを学んでいます。今はXMLファイルから適切なオブジェクトにデータをマッピングするクラスの単体テストを作成しようとしています。もちろん、クラスのすべての機能は、対応するXMLファイルの存在に依存しています。 XMLファイルはクラスのコンストラクタにロードされます。特定のファイルが必要なクラスを単体テストする方法

私はNUnitでC#を使用しています。テストでのファイルの存在をチェックすること行くための適切な方法であるので、これらの試験上の任意の提案はあまり歓迎されている場合

[Test] 
public void ShouldAllowInstanceToBeCreatedWhenXMLFileIsPresent() 
{ 
    if (File.Exists(SettingsReader.XML_SETTINGS_PATH)) 
    { 
     SettingsReader settingsReader = new SettingsReader(); 
     Assert.AreNotEqual(null, settingsReader); 
    } 
} 

[Test] 
[ExpectedException("Telekanzlei.Clientmanager.XMLDataLayer.XMLFileNotFoundException")] 
public void ShouldThrowExceptionWhenXMLFileIsNotPresent() 
{ 
    if (!File.Exists(SettingsReader.XML_SETTINGS_PATH)) 
    { 
     SettingsReader settingsReader = new SettingsReader(); 
    } 
     else 
      throw new XMLFileNotFoundException(); 
    } 

私はよく分からない。これまでのところ私は2つのテストを持っています。しかし、私の質問は、次のテストを進める方法です。 XMLファイルが存在しない場合は、明らかにすべての次のテストが失敗します。

私はXMLファイルが存在していると仮定していますが、失敗したテストはそれがそうでないことを念頭に置いていますか?それは私にとって正しいとは思わないでしょう。

このような問題を処理する一般的なパターンはありますか?任意のヘルプ

編集用

Thxを:実際にどのようなSettingsReader、あなたに伝えるために役立っている可能性があります。ファイルが実際に存在した場合、それが失敗していたとして...、

EDIT2を第二のテストを書き直しそうです。これまでのところ、それは次のようになります。

public class SettingsReader 
{ 
    public static readonly string XML_SETTINGS_PATH = "C:\\Telekanzlei\\Clientmanager_2.0\\Settings.xml"; 

    public XElement RootXElement { get; private set; } 

    public SettingsReader() 
    { 
     if (!File.Exists(XML_SETTINGS_PATH)) 
      throw new XMLFileNotFoundException(); 
     using (var fs = File.OpenRead(XML_SETTINGS_PATH)) 
     { 
      RootXElement = XElement.Load(fs); 
     } 
    } 


} 

私はわからないんだけど、私は、StreamReaderをここに行く方法ではないでしょうと思い、それでしょうか?

+3

設定リーダーは依存性注入を使用するように設計されていますか? DIとモックの良いケースのように聞こえる。 –

+1

MSTestには[DeploymentItem]があります。たぶんNUnitにそんなことがありますか? –

答えて

14

問題は単体テストではなく、クラスの設計にあります。クラスをリファクタリングしてファイルを開くのではなく、代わりにストリーム上で操作するようにすることをお勧めします。あなたの単体テストは単にメモリストリームのファイルストリームを置き換えることができます - simples! :)

public class SettingsReader() 
{ 
    public SettingsReader(System.IO.StreamReader reader) 
    { 
     // read contents of stream... 
    } 
} 

// In production code: 
new SettingsReader(new StreamReader(File.Open("settings.xml"))); 

// In unit test: 
new SettingsReader(new StringReader("<settings>dummy settings</settings>")); 

ファイルを開いて設定データを解析することは、2つの非常に異なる懸念事項です。

+0

私は、XElement.Loadメソッドがストリームをパラメータとして受け取っていることに気付きました。私はまだ.NETに精通していません。しかし、あなたの提案は良いアプローチのようです。ですから、私はそれを分割して、SettingsStreamProviderクラスとSettingsParserクラスを言い、パーサーに依存性注入を使用します。 – Tobi

+0

設定ストリームプロバイダークラスは単なるストリームに比べてどのような価値がありますか?私はそれが無意味な抽象化であると思う:KISS :) – MattDavey

+0

ポイントが取られた^^私は自分のプロジェクトで複数の機会にSettingsReaderを使用していますが、常に同じXMLファイルを使用しています。私はそれをとても好きではないでしょう、私はそれを使うたびに新しいストリームを "手動で"作成します。だからこそ、私は、まずはSettingsReaderクラスのストリームオープンを扱いたいと思っています。 – Tobi

5

SetUpの方法を使用して、ファイルが存在することをコピーまたは確認することをお勧めします。 ファイルがテストプロジェクトに追加されていることを確認し、それを再確認する必要がなくなったら「常にコピー」としてマークすることをお勧めします。
外部ファイルが必要なテストが多い場合は、おそらくMsTestを使用する必要があります。ファイルにDeploymentItemという属性があり、テストと同じ場所にファイルがコピーされます。

3

コードを書き直して、依存関係を渡すことができるようにするか、単体テストしたいコードにスタブしてください。

I.e. "IMySettingsFileProvider"インスタンスをSettingsReaderコンストラクタに渡します。ここで、IMySettingsFileProvider.SettingsXmlは設定ストリームを返します。この方法では、ディスク上にファイルが存在する必要はなく、テスト用のIMySettingsFileProviderインターフェイスをモックできます。

+1

それは少し "過労"ではないでしょうか? XMLファイルは、この単一のクラスでのみ使用されます。 Interface +クラスを作成するだけでファイルをロードできますか? – Tobi

+1

合意。私は人がなぜそれを行う "純粋な"方法であるというだけの理由で、あまりにも複雑なものを追加するのか理解していません。ファイルを作成したコードを利用して、そのファイルを作成/一時的な場所にコピーして使用し、削除した方がよいでしょう。 – tsells

+0

はい、そうかもしれません。それは私が「考える...」と書こうとした理由です。もしあなたがそうしているのであれば、もしそうでなければ、あなたの事件のために働くならば、何か他のことをしてください。 –

1

1つのオプションは、これをテストフィクスチャの上部に置くことです。テストが有効になるのは、ファイルが存在するときだけです。

[SetUp] 
public void Setup() 
{ 
    Assume.That(File.Exists(SettingsReader.XML_SETTINGS_PATH)); 
} 
関連する問題