Java Android JUnit未捕获Runtime.getRuntime().exec()中的IOException
我试图在Android设备上测试一些需要root权限的命令的执行情况。由于没有超级用户应用程序,我得到了一个Java Android JUnit未捕获Runtime.getRuntime().exec()中的IOException,java,android,junit,Java,Android,Junit,我试图在Android设备上测试一些需要root权限的命令的执行情况。由于没有超级用户应用程序,我得到了一个权限被拒绝错误,导致在尝试写入进程的输出流时引发IOException,这很好 但是,该异常虽然在使用调试器进行切换时可见,但JUnit既不会截获(因此测试以错误结束),也不会被调试器检测到以暂停执行 例外情况到哪里去了?如何修复测试,使异常在JUnit中导致错误 这是我的测试: String[] PWD = new String[] { "pwd" }; @Test public voi
权限被拒绝
错误,导致在尝试写入进程的输出流时引发IOException,这很好
但是,该异常虽然在使用调试器进行切换时可见,但JUnit既不会截获(因此测试以错误结束),也不会被调试器检测到以暂停执行
例外情况到哪里去了?如何修复测试,使异常在JUnit中导致错误
这是我的测试:
String[] PWD = new String[] { "pwd" };
@Test
public void testSudoForResult() throws IOException {
// this should throw IOException:
String result = SudoHelper.sudoForResult(PWD);
// these assertions are evaluated though they should not be, due to an error in the line above
assertNotNull(result);
assertTrue(result.length() > 0); // this assertion fails
}
以及测试中的代码:
public static String sudoForResult(String... commands) throws IOException {
List<String> allCommands = new ArrayList<>(commands.length+1);
allCommands.addAll(Arrays.asList(commands));
allCommands.add("exit");
return execForResult("/system/xbin/su", allCommands.toArray(new String[0]));
}
private static String execForResult(String command, String... strings) throws IOException {
String res = "";
DataOutputStream outputStream = null;
InputStream response = null;
InputStream errorStream = null;
String s = null;
try {
Process su = Runtime.getRuntime().exec(command);
response = su.getInputStream();
errorStream = su.getErrorStream();
if (strings != null) {
outputStream = new DataOutputStream(su.getOutputStream());
for (int i = 0; i < strings.length; i++) {
s = strings[i];
outputStream.writeBytes(s + "\n");
outputStream.flush();
}
}
try {
su.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
res = readFully(response);
} catch (IOException e) {
// I can step in here with a debugger, but it won't suspend when I put a breakpoint here
// The exception won't get caught by JUnit, even if I remove this catch block.
if (errorStream != null) {
// As expected, this will contain the message "Permission denied", due to the lack of Superuser app in my test case:
String errors = readFully(errorStream);
Log.e(TAG, "Error while processing command:" + s +": "+errors, e);
}
throw e;
} finally {
FileUtils.quietlyClose(outputStream);
FileUtils.quietlyClose(response);
}
return res;
}
public static String readFully(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = is.read(buffer)) != -1) {
baos.write(buffer, 0, length);
}
return baos.toString("UTF-8");
}
公共静态字符串sudoForResult(字符串…命令)引发IOException{
List allCommands=newarraylist(commands.length+1);
addAll(Arrays.asList(commands));
添加(“退出”);
返回execForResult(“/system/xbin/su”,allCommands.toArray(新字符串[0]);
}
私有静态字符串execForResult(字符串命令、字符串…字符串)引发IOException{
字符串res=“”;
DataOutputStream outputStream=null;
InputStream响应=null;
InputStream errorStream=null;
字符串s=null;
试一试{
进程su=Runtime.getRuntime().exec(命令);
response=su.getInputStream();
errorStream=su.getErrorStream();
if(字符串!=null){
outputStream=新的DataOutputStream(su.getOutputStream());
for(int i=0;i
更新:调试时我可以看到以下行为。在离开
finally
块后,我进入了一个catch块org.junit.internal.runners.model.ReflectveCallable#run()
,其中有一个InvokationTargetException
,其原因是我的IOException
。然后它被传播到Runner
的结构中,在那里它被EachTestNotifier#addFailure
使用,它似乎报告了失败,但它没有。你可以在调用SudoHelper.sudoForResult(PWD)
的区域周围放置一个try/catch
块。否则,异常不由您和JUnit处理,因为JUnit在调用testSudoForResult
方法时不处理异常。程序将崩溃,因此“未处理”代码之后的代码将不会运行
要解决此问题,代码可能更像这样:
@Test
public void testSudoForResult() /* no throwing exceptions here! */ {
String result = "";
try {
result = SudoHelper.sudoForResult(PWD);
} catch(IOException ex) {
//handle exception however you want, maybe with e.printStackTrace()
}
assertNotNull(result);
assertTrue(result.length() > 0);
}
您可以在调用
SudoHelper.sudoForResult(PWD)
的区域周围放置一个try/catch
块。否则,异常不由您和JUnit处理,因为JUnit在调用testSudoForResult
方法时不处理异常。程序将崩溃,因此“未处理”代码之后的代码将不会运行
要解决此问题,代码可能更像这样:
@Test
public void testSudoForResult() /* no throwing exceptions here! */ {
String result = "";
try {
result = SudoHelper.sudoForResult(PWD);
} catch(IOException ex) {
//handle exception however you want, maybe with e.printStackTrace()
}
assertNotNull(result);
assertTrue(result.length() > 0);
}
我希望在抛出异常时测试失败。我已经尝试过这个解决方案,在catch块中调用了
fail()。不幸的是,它也没有被调用。我希望在抛出异常时测试失败。我已经尝试过这个解决方案,在catch块中调用了fail()。不幸的是,它也没有被调用。