0

我正在学习 JUnit,但不应该像这样使用 assertTrue(..) :

anObject myObject=anObject();
myObject.assertTrue(...);

我不太明白的部分是,在OO语言中,突然出现这个没有对象的方法调用,它似乎暗示了JUnit.assertTrue(...),这就是我的理解,但这没有提到,我对么 ?

如果是这样,那么“结果结果 = JUnitCore.runClasses(TestJunit.class);” 应该是这样的:

Result result = runClasses(TestJunit.class);

为什么不一致?我错过了什么吗?

4

2 回答 2

3

首先,assertTrue它的亲戚(assertFalse, assertThat)都是静态方法。一个人会导入他们选择的断言的静态方法(并且存在于 中Assert,因此assertTrue是 的简写Assert.assertTrue)。

其次,断言是相对于对象发生的,但不是作为它的属性。在我看来,如果断言是对象的实际属性,那么对具体对象进行断言是没有意义的。

第三,当您检索结果时(我认为这就是您正在做的事情),您希望从您正在测试的具体对象中得到答案。我不理解您用于检索的构造Result,因为您打算在单元测试中测试的只是一些代码单元——一些小的、易于验证的东西,并且不会主动干扰重构工作。


以下是我通常会如何编写单元测试。希望这能让您澄清我想要从我的测试中得到什么,以及我将要测试什么。

用例:我编写了一个实用程序来检索两个之间的集合差异Lists,但明显的警告是可能存在重复。这是我记得为另一个答案整理的一些代码,但我非常喜欢它,因此我对其进行了改进,并编写了测试以确保行为。

public static List<Integer> difference(List<Integer> leftList, List<Integer> rightList) {
    if(null == leftList || null == rightList) {
        throw new IllegalArgumentException("Can't have any null parameters.");
    }
    if(leftList.size() < rightList.size()) {
        throw new IllegalArgumentException("Left shouldn't be larger than right.");
    }

    List<Integer> result = new LinkedList<>();
    int i = 0;
    int j = 0;
    while (i < leftList.size()) {
        while (j < rightList.size()) {
            Integer leftElement = leftList.get(i);
            Integer rightElement = rightList.get(j);
            if(rightElement.compareTo(leftElement) <= 0) {
                // less than or equal to.  Skip.
                i += 1;
                j += 1;
                break;
            }
            if(rightElement.compareTo(leftElement) > 0) {
                // The right-hand side is greater than the left hand side.
                // Add it to the results.
                result.add(leftElement);
                i++;
                break;
            }
            j++;
        }
    }
    return result;
}

这就是单元测试的样子。请注意我在原则上是如何断言一件事的。它违反了 OO 的某些原则,但是当您编写测试时,您想要断言行为和结果。

@Test
public void testDifference() throws Exception {
    //given
    List<Integer> left = Lists.newArrayList(1, 2, 3, 4, 5);
    List<Integer> right = Lists.newArrayList(1, 2, 4, 5);

    //when
    List<Integer> result = SetUtils.difference(left, right);

    //then
    assertEquals(Lists.newArrayList(3), result);
}

@Test
public void testDifference2() throws Exception {
    //given
    List<Integer> left = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 9, 10);
    List<Integer> right = Lists.newArrayList(1, 2, 4, 5, 10);

    //when
    List<Integer> result = SetUtils.difference(left, right);

    //then
    assertEquals(Lists.newArrayList(3, 6, 7, 9), result);
}

如果您一直走到这一步,让我来说明在这种行为中编写单元测试的好处之一。如果我想放弃使用 while 循环,而是使用foreach,我现在可以自信地执行重构;单元测试的结构方式让我一眼就能看到并期待我从这段代码中真正想要的行为。

老实说,如果有效性是静态的一部分,我无法想象尝试这样做。那将很难实现。

于 2013-07-03T02:17:05.250 回答
1

在这种情况下assertTrue是一个静态方法,定义在Assert.java.

因此,您的源代码通常import static org.junit.Assert.*;会使该类中的所有静态方法Assert在测试源代码中可用。您也可以像 JUnit入门指南中所做的那样,仅静态导入单个方法,例如assertEquals方法。Java 1.5 中引入了静态导入。

面向对象的语言通常提供一种方法来编写不对对象的特定实例(例如,SmalltalkScala)进行操作的方法。

于 2013-07-03T02:12:56.187 回答