1

私はpowermockを使用して、プロセスビルダーを使用してネイティブコマンド呼び出しをモックしています。奇妙なことに、これらのテストは時々合格し、時には失敗してNPEを与えます。これはパワーモックの問題ですか、それともプログラムの落とし穴ですか。

これが私がテストしているクラスのスニペットです:

public void method1(String jsonString, String filename) {
  try {
    JSONObject jObj = new JSONObject(jsonString);
    JSONArray jArr = jObj.getJSONArray("something");

    String cmd = "/home/y/bin/perl <perlscript>.pl<someConstant>" + " -k " + <someConstant> + " -t " + <someConstant>;

    cmd += vmArr.getJSONObject(i).getString("jsonKey");

    ProcessBuilder pb = new ProcessBuilder("bash", "-c", cmd);
    pb.redirectErrorStream(false);
    Process shell = pb.start();
    shell.waitFor();
    if (shell.exitValue() != 0) {
      throw new RuntimeException("Error in Collecting the logs. cmd="+cmd);
    }
    StringBuilder error = new StringBuilder();
    InputStream iError = shell.getErrorStream();
    BufferedReader bfr =
      new BufferedReader(
      new InputStreamReader(iError));
    String line = null;
    while ((line = bfr.readLine()) != null) {
      error.append(line + "\n");
    }
    if (!error.toString().isEmpty()) {
      LOGGER.error(error`enter code here`);
    }
    iError.close();
    bfr.close();
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}

単体テストケースは次のとおりです。

@PrepareForTest( {<Classtobetested>.class, ProcessBuilder.class,Process.class, InputStream.class,InputStreamReader.class, BufferedReader.class} )
@Test(sequential=true)
public class TestClass {

@Test(groups = {"unit"})
public void testMethod() {
  try {
    ProcessBuilder prBuilderMock = createMock(ProcessBuilder.class);
    Process processMock = createMock(Process.class);
    InputStream iStreamMock = createMock(InputStream.class);
    InputStreamReader iStrRdrMock = createMock(InputStreamReader.class);
    BufferedReader bRdrMock = createMock(BufferedReader.class);
    String errorStr =" Error occured";

    String json = <jsonStringInput>;
    String cmd = "/home/y/bin/perl <perlscript>.pl -k "+<someConstant>+" -t "+<someConstant>+" "+<jsonValue>;

    expectNew(ProcessBuilder.class, "bash", "-c", cmd).andReturn(prBuilderMock);
    expect(prBuilderMock.redirectErrorStream(false)).andReturn(prBuilderMock);
    expect(prBuilderMock.start()).andReturn(processMock);
    expect(processMock.waitFor()).andReturn(0);
    expect(processMock.exitValue()).andReturn(0);
    expect(processMock.getErrorStream()).andReturn(iStreamMock);
    expectNew(InputStreamReader.class, iStreamMock)
                .andReturn(iStrRdrMock);
    expectNew(BufferedReader.class, iStrRdrMock)
                .andReturn(bRdrMock);
    expect(bRdrMock.readLine()).andReturn(errorStr);
    expect(bRdrMock.readLine()).andReturn(null);
    iStreamMock.close();
    bRdrMock.close();
    expectLastCall().once();
    replayAll();
    <ClassToBeTested> instance = new <ClassToBeTested>();
    instance.method1(json, fileName);
    verifyAll();
  } catch (Exception e) {
    Assert.fail("failed while collecting log.", e);
  }
}

実行時にエラーが発生し、テストケースが失敗します。

Caused by: java.lang.NullPointerException
at java.lang.ProcessBuilder.start(ProcessBuilder.java:438)

注:すべての実行でこのエラーが発生するわけではありません。合格することもあれば、失敗することもあります。私はこの振る舞いを理解することができません。また、著作権の問題のため、いくつかの変数名をカモフラージュしました。

4

1 に答える 1

0

コンストラクター呼び出しをモックしているため、コードを壁として準備する必要があります。これは、コンストラクターの呼び出しがコードの一部であるためです。詳細については、PowerMock のドキュメントを参照してください: http://code.google.com/p/powermock/wiki/MockConstructor

于 2010-08-27T08:04:18.793 に答える