【问题标题】:catching an exception after doThrow JUNIT在 doThrow JUNIT 之后捕获异常
【发布时间】:2014-04-25 04:41:28
【问题描述】:

我有一个 JUnit 测试,我正在测试一个带有空参数的方法。如果参数 /arguments 为 null,那么我将抛出 NullPointerException。该方法本身只会抛出一个 IOException。我在类的模拟对象上使用 doThrow,但在我看来,我正在丢失 doThrow() 构造中的异常并且我无法捕获它。此外,我绝对不想在我的单元测试中使用 try catch。所以我同样使用@Rules。这是代码sn-p:

public class TableTest {

@Rule
public ExpectedException exception = ExpectedException.none();
private static Table spyTable;

@Test
public void testCreateTableWithNullTableName_throwsIOEXception() throws IOException {
    final String tableName = null;
    mockConfig = mock(Configuration.class);
    spyPersonTable = spy(new PersonTable());
    doThrow(new IllegalArgumentException()).when(spyPersonTable).createTable(tableName, mockConfig);
    // exception.expect(IllegalArgumentException.class);
}

使用@rule 的异常对象,如果我使用注释行来捕获我的异常,在doThrow() 构造中创建的异常将丢失并且我无法捕获它。我的单元测试将失败并抱怨:

Expected test to throw an instance of java.lang.IllegalArgumentException

如果我按照我的方式注释了该行,则测试工作正常。这是我正在尝试测试的方法的样子:

public void createTable(final String tableName, final Configuration config) throws IOException 

该方法需要抛出 IOException,因为创建表时抛出的特定异常是 IOException 的子类。

对于这种类型的检查异常,我在 JUnit 测试中捕获的异常是否错误。

【问题讨论】:

  • "我绝对不想在我的单元测试中使用 try catch"
  • 只是给我的一个要求。
  • 还有实际抛出的异常吗?
  • 好吧,方法“createTable”只是没有专门抛出 IllegalArgumentException。在方法体的开头,我有检查 null 等的前提条件
  • 而前提是什么?如果.checkNotNull() 它将在失败时抛出 NPE,而不是 IllegalArgumentException。如果是这种情况,你不应该.doThrow(),甚至spy() 都不需要,因为这是你唯一想要测试的东西

标签: java exception junit mocking mockito


【解决方案1】:

您似乎想测试该方法是否抛出异常;但是通过使用doThrow().when(sut).createTable(...),您阻止 SUT 具有正常行为。

只要做:

final PersonTable table = new PersonTable();
table.createTable(null, null); // theoretically throws IllegalArgumentException

然后检查是否有抛出异常。不知道您是如何使用 @Rule 做到这一点的,但我不使用它,这里我将如何做到这一点:

final PersonTable table = new PersonTable();
try {
    table.createTable(null, null);
    fail("No exception thrown!");
} catch (IllegalArgumentException e) {
    assertEquals(e.getMessage(), "the expected message");
}

【讨论】:

  • 这个测试仍然失败,但我明白了它背后的想法,可以从这里开始。我仍然不明白,当我说类似以下内容时: public void someTestName() throws IOException{ } 但如果我传递空参数,我也会抛出 IllegalArgumentException。我也应该在 testName 声明中抛出这个异常吗?
  • 你不必这样做,因为IllegalArgumentException 是一个未经检查的异常
  • 抛出 IOException 的原因是,我的 createTable 方法抛出了 IOException,任何调用该方法的测试方法都需要抛出 IOException
  • 那就不要使用Preconditions ;)
  • 该死的......当我有东西要审查时,不想有这么多的设计更改......!!!
【解决方案2】:

您的问题是您的测试实际上并没有调用createTable,因此没有什么可以抛出异常。你可以写这个。

@Test
public void testCreateTableWithNullTableName_throwsIOEXception() throws IOException {
    final String tableName = null;
    mockConfig = mock(Configuration.class);
    spyPersonTable = spy(new PersonTable());
    doThrow(new IllegalArgumentException()).when(spyPersonTable).createTable(tableName, mockConfig);
    exception.expect(IllegalArgumentException.class);
    spyPersonTable.createTable(tableName, mockConfig);
}

但我真的不明白这样做有什么意义,因为你真的只是在测试 Mockito。您正在对该方法进行存根,以便它除了抛出 IllegalArgumentException 之外什么都不做,然后检查您的存根是否工作正常 - 这对我来说似乎毫无意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 2021-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多