【问题标题】:How to test exceptions with assertThrows如何使用 assertThrows 测试异常
【发布时间】:2018-06-21 15:25:02
【问题描述】:

我有一个名为“foo”的函数,它产生一个字符串数组列表。 foo 总是返回一个大小为 2 的非空数组。当我尝试访问超出范围的元素时,我应该得到“IndexOutOfBounds”异常。测试方法有两种变体。第二个失败,而第一个工作正常。您认为导致第二个失败的原因是什么?

我尝试使用 assertThrows 检查异常,但没有按预期工作。

import java.util.ArrayList;

public class fooClass {

    static ArrayList<String> foo (){
        ArrayList<String> arrayOfSize2 = new ArrayList<String>();
        arrayOfSize2.add("x");
        arrayOfSize2.add("y");
        return arrayOfSize2;
    }    
}

以下测试块正在工作

@Test
void testFoo() {
    ArrayList<String> dummyArrayList = FooClass.foo();
    assertEquals("x",dummyArrayList.get(0));
    assertEquals("y",dummyArrayList.get(1));
    assertThrows(IndexOutOfBoundsException.class, () -> dummyArrayList.get(2));
}

但是这个不行

@Test
void testFoo() {
    ArrayList<String> dummyArrayList = new ArrayList<String>();
    dummyArrayList=fooClass.foo();
    assertEquals("x", dummyArrayList.get(0));
    assertEquals("y", dummyArrayList.get(1));
    assertThrows(IndexOutOfBoundsException.class, () -> dummyArrayList.get(2));
}

我希望第二个代码的 assertThrows 输出也是 True,但实际输出是 Local variable dummyArrayList defined in an enclosing scope must be final or effectively final

【问题讨论】:

  • 您是说您在上面发布的代码中得到“必须是最终的或有效的最终”,还是您简化的更“复杂情况”?按照编码,它对我来说完美无缺,抛出异常,断言成功。
  • 您刚刚发现了另一个需要解决的难题。似乎我在简化问题的同时偏离了目标。在原始代码中,我初始化了 dummyArrayList,然后分配了函数的返回值。我将通过添加一个完整的示例来改进帖子。
  • 感谢您更新代码。实际上,Rahul B 是正确的(尽管他在发布时不知道),这里唯一的问题是 dummyArrayList 被分配了两次,然后在 lambda 中使用。我相信你可以看到第一行是没有用的,对吧?只需将这两行组合起来,就不会重新分配 dummyArrayList(这为您提供了工作测试方法),您会没事的。
  • 感谢您的评论。我可以看到第二个测试块的第一行是没有意义的,但是由于我希望它具有最后一个分配的值,所以我不完全理解失败背后的原因。从我的角度来看:ArrayList&lt;String&gt; dummyArrayList = FooClass.foo(); 等于 ArrayList&lt;String&gt; dummyArrayList = new ArrayList&lt;String&gt;(); dummyArrayList=fooClass.foo();
  • Caglar,是的,它们是相同的,但是将其分配两次意味着 dummyArrayList 更改。为了使用在闭包外部声明的变量,它的引用不能改变。即使您知道这无关紧要(因为闭包将使用分配的第二个实例),Java 编译器也会拒绝,因为它要求它是“最终的或有效的最终”。

标签: unit-testing lambda exception-handling java-8 junit5


【解决方案1】:

我认为您的方法是错误的,因为它也会在 foo() 方法返回少于 2 个元素的列表或 null 的可能性很小的情况下异常终止。

我会按这个顺序测试它:

@Test
void testFoo() {
    ArrayList<String> dummyArrayList = FooClass.foo();
    assertNotNull(dummyArrayList);
    assertEquals(2,dummyArrayList.size());
    assertEquals("x", dummyArrayList.get(0));
    assertEquals("y", dummyArrayList.get(1));
}

[编辑] 甚至更简单:

@Test
void testFoo() {
    ArrayList<String> dummyArrayList = FooClass.foo();
    assertIterableEquals(Arrays.asList("x", "y"), dummyArrayList);
}

【讨论】:

  • 感谢您的留言。我实际上是在使用这个程序来测试一个复杂的情况。我想简化这个问题,以便人们能够理解。因此,在这种情况下,我们可以假设 foo 不返回空集合或小于大小 2 的集合。
  • 您可能想要使用assertIterableEquals 而不是assertEquals
【解决方案2】:

lambda 表达式中使用的变量应该是有效的最终变量。断言很好,但 lambda 抱怨

【讨论】:

    猜你喜欢
    • 2020-09-21
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-23
    相关资源
    最近更新 更多