2009-07-13 17 views
5

私はVS 2008の組み込みユニットテストフレームワークでC#ユニットテストを作成しようとしており、テストするメソッドはEnvironment.Exit(0)です。私のユニットテストでこのメソッドを呼び出すと、私のユニットテストは中止されます。このメソッドは実際にはExitを呼び出す必要があります。私はそれが行うことをテストする方法と、それが使用する終了コードをテストする方法が必要です。どうすればいい?私はMicrosoft.VisualStudio.TestTools.UnitTesting Namespaceを見ましたが、関連性があると思われるものは見ませんでした。VS2008ユニットテスト - アサートメソッド終了

[TestMethod] 
[DeploymentItem("myprog.exe")] 
public void MyProgTest() 
{ 
    // Want to ensure this Exit's with code 0: 
    MyProg_Accessor.myMethod(); 
} 

。一方、ここで私がテストしたいコードの要旨だ:

static void myMethod() 
{ 
    Environment.Exit(0); 
} 

編集:ここで私は私のテスト方法、RichardODのおかげで使用するソリューションです:

Process proc; 

try 
{ 
    proc = Process.Start(path, myArgs); 
} 
catch (System.ComponentModel.Win32Exception ex) 
{ 
    proc = null; 
    Assert.Fail(ex.Message); 
} 

Assert.IsNotNull(proc); 
proc.WaitForExit(10000); 
Assert.IsTrue(proc.HasExited); 
Assert.AreEqual(code, proc.ExitCode); 

答えて

4

これは非常に悪い考えです。 Environment.Exit(0)は、明らかに処方されているように、なぜあなたのユニットテストが壊れているのでしょうか。

これをまだテストしたい場合は、別のプロセスを起動してリターンコードを確認することで、Process.Startにラップしてください。

もう1つの選択肢は、このコードを分解してtest spyを注入するか、モックオブジェクトを使用して正しい動作を確認することです。

おそらくあなたはTypemock Isolatorで何かできます - これはあなたにmock static methodsを与えると信じています。

+0

1 - それはあなたがインターセプトし、絶対に何かを模擬することができますそのうち私は承知している唯一のソリューションです。 –

+0

静的メソッドをモックすることができるという危険性は、あなたが簡単にそれらを使用することから離れないことです。私は実際には(私のコードのために)静的メソッドを持つために余分な努力を余儀なくされていることがわかります。これはより良い技術、IMOを使用して開発を強制するのに役立ちます。欠点は、それらの静的メソッドが意味をなされているときに相互作用するとき(またはフレームワークがテストを念頭に置いて構築されていない場合)、フープを突き抜けなければならないことです。 – tvanfosson

+0

@ tvanfosson-それは良い点です。そのため、テスト可能なコードを書くときに静的メソッドを過度に使用することを避けるために、多くの人が(私自身も含めて)なぜそうしようとしています静的な.NETフレームワーククラスは痛みテストであり、開発者はしばしばラッパーコードを記述してテスト可能にする必要があります(回答ごとに)。 ASP.NET WebフォームからASP.NET MVCへの進化から、これは多くのことがわかります。 – RichardOD

3

これをテストすることはできません。Environment.Exitはアプリケーションを完全に終了します。これは、このコードを使用するすべてのAppDomainが、プロダクションアプリケーションであろうと単体テストフレームワークであろうと、完全にアンロードされることを意味します。

2

ここで唯一選択できるのは、Environmentクラスをfakie Exitメソッドでモックすることです。

5

Environmentクラス用のラッパーを作成し、コード内にラッパーを使用する必要があります。あなたのユニットテストのために、ラッパーのモックバージョンを注入してください。次の例では、RhinoMockを使用して、メソッドが期待される引数でラッパーを呼び出すことを確認します。

public class EnvironmentWrapper 
{ 
    public virtual void Exit(int code) 
    { 
     Environment.Exit(code); 
    } 
} 


public class MyClass 
{ 
    private EnvironmentWrapper Environment { get; set; } 

    public MyClass() : this(null) { } 

    public MyClass(EnvironmentWrapper wrapper) 
    { 
     this.Environment = wrapper ?? new EnvironmentWrapper(); 
    } 

    public void MyMethod(int code) 
    { 
     this.Environment.Exit(code) 
    } 
} 


[TestMethod] 
public void MyMethodTest() 
{ 
    var mockWrapper = MockRepository.GenerateMock<EnvironmentWrapper>(); 

    int expectedCode = 5; 

    mockWrapper.Expect(m => m.Exit(expectedCode)); 

    var myClass = new MyClass(mockWrapper); 

    myclass.MyMethod(expectedCode); 

    mockWrapper.VerifyAllExpectations() 
} 
+1

+1。いい例ですが、私が夕食を食べていないと、私はそれらの行に沿って何かをコーディングするつもりでした!あなたのコードは、ASP.NET MVCプロジェクトAccountControllerクラスのデフォルトコードを思い出させます。これは良いことに過ぎません。個人的に私はPublic EnvironmentWrapper Environment {get;セット; }をプライベートセットに変換しますが、その素晴らしい例は別です。 – RichardOD

+0

@ RichardOD - 公開/非公開で合意しました。更新されます。 – tvanfosson

0

メソッドに引数を追加して、exit()メソッドが終了しない偽の環境に渡すことができます。

アプリケーションから呼び出されたメソッドから抽出されたこのパラメータ化されたメソッドを抽出し、抽出された関数をユニットテストすることができます。そうすれば、アプリを変更する必要はありません。

0

私の心に来るだけの事は一緒に何かある:ここTypeMockアイソレータの

static void myMethod() 
{ 
    DoEnvironmentExit(0); 
} 

static void DoEnvironentExit(int code) 
{ 
    #if defined TEST_SOLUTION 
     SomeMockingFunction(code); 
    #else 
     Environment.Exit(code); 
    #endif 
} 
関連する問題