为什么Mockito跳过了我的抽象类的成员变量的初始化



我正在尝试测试一个抽象类,而Mockito没有初始化我的成员变量。这里有一个简单的例子来告诉你我的问题。

这是一个初始化其"字段"成员的抽象类:

import java.util.ArrayList;
import java.util.Collection;
public abstract class Foo {
    private final Collection field = new ArrayList();
    protected Foo() {
        System.out.println("In constructor");
    }
    public boolean isNull(Object o) {
        field.add(o);
        return o == null;
    }
    abstract void someAbstractMethod();
}

这里的测试类别:

import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
public class FooTest {
    @Test
    public void testSomething() {
        final Foo foo = Mockito.mock(Foo.class);
        Mockito.when(foo.isNull(Mockito.anyObject())).thenCallRealMethod();
        Assert.assertFalse(foo.isNull("baaba"));
    }
}

当测试运行时,它会抛出一个NPE,因为变量"field"未初始化!

我做错了什么?

这是预期的行为,当您模拟某个东西时,创建的实例是一个完整的模拟,因此初始化字段是没有意义的,因为行为是默认的

除此之外,字段可以由具体或抽象类中的构造函数初始化,因为mock实例化仅仅因为是mock而绕过构造函数,所以初始化它们更不合理。

在使用mock时,尝试调用real方法通常是错误的。相反,应该截断mock的行为。

Mockito.when(foo.isNull(Mockito.anyObject())).thenReturn(false);
Assert.assertFalse(foo.isNull("baaba")); // assertion always passing

我不知道你的实际用例,但也许你想要一个带有spy的部分mock。尽管这仍然被认为是一种糟糕的做法,因为它通常意味着你需要重构代码以使用组合。

您似乎在嘲笑实际要测试的类。这不是真正的嘲笑。您对测试范围之外的类进行模拟,并将正在测试的东西保持不变。

在这种情况下,您可能只需要创建一个Foo,并使用someAbstractMethod的伪实现来直接测试它。就我所见,没有必要嘲笑。

相关内容

  • 没有找到相关文章

最新更新