20

EasyMockを使用してへの呼び出しを期待する最善の方法について誰かが提案できますRuntime.getRuntime().exec(xxx)か?

インターフェイスを実装する別のクラスのメソッドに呼び出しを移動することはできますが、理想的な世界ではそうではありません。

interface RuntimeWrapper {
    ProcessWrapper execute(String command) throws IOException;
}

interface ProcessWrapper {
    int waitFor() throws InterruptedException;
}

誰か他に何か提案があったかしら?

4

4 に答える 4

15

あなたのクラスはを呼び出すべきではありませんRuntime.getRuntime()Runtime依存関係としてが設定されていることを期待し、それを処理する必要があります。次に、テストでモックを簡単に提供し、依存関係として設定できます。

補足として、テスト容易性のためのOO設計に関するこの講義をご覧になることをお勧めします。

更新:プライベートコンストラクターが表示されませんでした。別のコンストラクターを追加したり、コンストラクターをパブリックにしたりするためにJavaバイトコードインストルメンテーションを使用してみることができますが、それも不可能であることが判明する可能性があります(そのクラスにいくつかの制限がある場合)。

したがって、(質問で提案したように)ラッパーを作成し、依存性注入のアプローチに従うことを選択できます。

于 2010-02-13T14:48:18.643 に答える
8

上記のBozhoはIMOの正しい解決策です。しかし、それが唯一の解決策ではありません。PowerMockまたはJMockItを使用できます。

PowerMockの使用:

package playtest;

public class UsesRuntime {
    public void run() throws Exception {
        Runtime rt = Runtime.getRuntime();
        rt.exec("notepad");
    }
}


package playtest;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.legacy.PowerMockRunner;

import static org.powermock.api.easymock.PowerMock.*;
import static org.easymock.EasyMock.expect;

@RunWith(PowerMockRunner.class)
@PrepareForTest( { UsesRuntime.class })
public class TestUsesRuntime {

    @Test
    public void test() throws Exception {
        mockStatic(Runtime.class);
        Runtime mockedRuntime = createMock(Runtime.class);

        expect(Runtime.getRuntime()).andReturn(mockedRuntime);

        expect(mockedRuntime.exec("notepad")).andReturn(null);

        replay(Runtime.class, mockedRuntime);

        UsesRuntime sut = new UsesRuntime();
        sut.run();
    }
}
于 2010-02-15T14:50:29.690 に答える
1

おそらく、モックする代わりにRuntime.getRuntime().exec()、スクリプト/プログラムなどを「モック」することができます。呼び出しているはずです。

実際のコマンドライン文字列をに渡す代わりにexec()、テストスクリプトを記述して実行します。モッククラスのように、テストできるハードコードされた値をスクリプトに返すことができます。

于 2010-02-13T20:52:08.170 に答える
0

EasyMock 3.0(およびJUnit 4)でこれを行う方法は次のとおりです。

import org.junit.*;
import org.easymock.*;
import static org.easymock.EasyMock.*;

public final class EasyMockTest extends EasyMockSupport
{
    @Test
    public void mockRuntimeExec() throws Exception
    {
         Runtime r = createNiceMock(Runtime.class);

         expect(r.exec("command")).andReturn(null);
         replayAll();

         // In tested code:
         r.exec("command");

         verifyAll();
    }
}

上記のテストの唯一の問題は、Runtimeオブジェクトをテスト対象のコードに渡す必要があることです。これにより、オブジェクトを使用できなくなりRuntime.getRuntime()ます。一方、JMockitを使用すると、次のテストを記述して、その問題を回避できます。

import org.junit.*;
import mockit.*;

public final class JMockitTest
{
    @Test
    public void mockRuntimeExec() throws Exception
    {
        final Runtime r = Runtime.getRuntime();

        new NonStrictExpectations(r) {{ r.exec("command"); times = 1; }};

       // In tested code:
       Runtime.getRuntime().exec("command");
    }
}
于 2010-08-30T13:37:31.410 に答える