【问题标题】:Testing Expected Exceptions with ActivityInstrumentationTestCase2使用 ActivityInstrumentationTestCase2 测试预期异常
【发布时间】:2015-08-09 13:28:42
【问题描述】:

我想对这个简单的活动进行单元测试(请关注 onClick() 函数):

public class MainActivity extends Activity implements OnClickListener {

    private EditText edtValue1;
    private EditText edtValue2;
    private TextView txtResult;
    private Button btnAdd;
    private Button btnMuliply;

    private ICalculator calculator;

    final String LOG_TAG = "MainScreen";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        edtValue1 = (EditText) findViewById(R.id.value1);
        edtValue2 = (EditText) findViewById(R.id.value2);
        txtResult = (TextView) findViewById(R.id.result);
        btnAdd = (Button) findViewById(R.id.addValues);
        btnMuliply = (Button) findViewById(R.id.multiplyValues);

        btnAdd.setOnClickListener(this);
        btnMuliply.setOnClickListener(this);

        calculator = new Calculator();
    }

    @Override
    public void onClick(View v) {

        int val1 = 0;
        int val2 = 0;

        try {
            val1 = Integer.parseInt(edtValue1.getText().toString());
            val2 = Integer.parseInt(edtValue2.getText().toString());
        } 
        catch (NumberFormatException exc) {
            Log.e(LOG_TAG, exc.getMessage(), exc);
            throw exc;
        }

        switch (v.getId()) {

        case R.id.addValues:
            txtResult.setText(calculator.addNumbers(val1, val2).toString());
            break;

        case R.id.multiplyValues:
            txtResult.setText(calculator.multiplyNumbers(val1, val2).toString());
            break;
        }

    }
}

外观是这样的:

这里是简单的JUnit测试用例(请关注testAddDecimalValues_NumberFormatException()方法):

public class MainActivityTest extends
        ActivityInstrumentationTestCase2<MainActivity> {

    MainActivity mainActivity;
    private TextView txtResult;


    public MainActivityTest() {
        super(MainActivity.class);
    }

    @Before
    public void setUp() throws Exception {
        mainActivity = getActivity();
        txtResult = (TextView) mainActivity.findViewById(R.id.result);
    }

    private final static String NUMBER_24 = "2 4 ENTER ";
    private final static String NUMBER_74 = "7 4 ENTER ";
    private final static String ADD_RESULT = "98";


    @After
    protected void tearDown() throws Exception {

    }

    @Test
    public void testAddValues() {
        sendKeys(NUMBER_24 + NUMBER_74 + "ENTER");

        // get result
        String mathResult = txtResult.getText().toString();
        assertTrue("Add result should be 98", mathResult.equals(ADD_RESULT));
    }



    private final static String NUMBER_5_DOT_5 = "5 PERIOD 5 ENTER ";

    @Test(expected = NumberFormatException.class)
    public void testAddDecimalValues_NumberFormatException() {
            sendKeys(NUMBER_5_DOT_5 + NUMBER_74 + "ENTER");
    }

}

当我启动单元测试时 testAddValues() 工作正常,但 testAddDecimalValues_NumberFormatException() 方法没有考虑到 expected = IllegalArgumentException.classtestAddDecimalValues_NumberFormatException() 测试失败...

这里是 Logcat:

[2015-05-27 12:52:42 - SimpleCalcTest] Launching instrumentation android.test.InstrumentationTestRunner on 0123456789ABCDEF
[2015-05-27 12:52:42 - SimpleCalcTest] Test run failed: Instrumentation run failed due to 'Process crashed.'
[2015-05-27 12:52:42 - SimpleCalcTest] Test run finished
[2015-05-27 12:52:43 - SimpleCalcTest] Sending test information to Eclipse
[2015-05-27 12:52:44 - SimpleCalcTest] Test run failed: Instrumentation run failed due to 'java.lang.NumberFormatException'
[2015-05-27 12:52:44 - SimpleCalcTest] Test run finished

问题是:您知道如何使用 ActivityInstrumentationTestCase2 功能测试预期的异常吗?

非常感谢。

PS : 我尝试了与 http://www.javacodegeeks.com/2013/02/testing-expected-exceptions-with-junit-rules.html 不同的方法,但我得到了相同的结果

【问题讨论】:

    标签: android eclipse unit-testing junit


    【解决方案1】:

    ActivityInstrumentationTestCase2 扩展了junit.framework.TestCase,因此您不能将org.junit 树中的注释或类(如@TestExpectedException)与使用ActivityInstrumentationTestCase2 的测试一起使用

    相反,这样做:

    public void testAddDecimalValues_NumberFormatException() {
      try {
        sendKeys(NUMBER_5_DOT_5 + NUMBER_74 + "ENTER");
        fail("NumberFormatException not thrown");
      } catch (NumberFormatException expected) {
      }
    }
    

    编辑:第二个问题是你的非测试代码。当你捕获一个异常时,你只有三个选择:

    1. 捕获异常,记录异常,然后继续前进而不抛出异常
    2. 捕获异常,用另一个异常包装异常,然后抛出新异常(不记录)。
    3. 重试操作 1-n 次,如果仍然失败,请执行选项 1 或 2(仅供专家使用;此选项可能对远程调用有意义,并且您需要了解抛出循环异常)

    注意选项 2 异常将由调用代码处理或由调用代码记录,因此如果您打算抛出异常,则无需记录该异常。

    所以替换这个:

    try {
      val1 = Integer.parseInt(edtValue1.getText().toString());
      val2 = Integer.parseInt(edtValue2.getText().toString());
    } catch (NumberFormatException exc) {
      Log.e(LOG_TAG, exc.getMessage(), exc);
      throw exc;
    }
    

    有了这个:

    val1 = Integer.parseInt(edtValue1.getText().toString());
    val2 = Integer.parseInt(edtValue2.getText().toString());
    

    【讨论】:

    • 我已经尝试过这个解决方案(根据这个链接link)。此日志出现:[2015-05-27 18:07:33 - SimpleCalcTest] 在 0123456789ABCDEF 上启动仪器 android.test.InstrumentationTestRunner [2015-05-27 18:07:34 - SimpleCalcTest] 向 Eclipse 发送测试信息 [2015-05 -27 18:07:37 - SimpleCalcTest] 测试运行失败:由于“java.lang.NumberFormatException”,检测运行失败 [2015-05-27 18:07:37 - SimpleCalcTest] 测试运行完成
    【解决方案2】:

    最后,我认为 ActivityInstrumentationTestCase2 无法测试预期的异常,因为 ActivityInstrumentationTestCase2 用于自动化手动测试,并且手动测试不能满足异常。 .. 这就是为什么为了测试错误案例,我们必须只在业务类上进行单元测试。

    MainActivity 类中,我必须处理异常。如果你愿意,我可以发布我的代码解决方案。

    谢谢

    【讨论】:

      猜你喜欢
      • 2011-07-31
      • 2019-01-23
      • 1970-01-01
      • 2012-04-05
      • 2013-10-08
      • 1970-01-01
      • 1970-01-01
      • 2015-07-31
      • 2011-05-28
      相关资源
      最近更新 更多