是否可以调用mocked对象的方法?

时间:2014-07-07 20:10:01

标签: java unit-testing reflection mockito

例如,我有这个课程:

public class A {
    private List<String> list;

    public A(B b){
        list = b.getList();
    }

    public List<String> someMethod(){
        return list;
    }
}

我想在不调用构造函数的情况下对单元测试someMethod进行单元测试。我使用 reflection 来设置list

问题在于我不想创建B类对象而且我无法模拟它,因为它会导致NPE。

所以我的问题是:

如何在不调用someMethod的构造函数的情况下测试A?有没有办法模拟A类,并且没有失去调用方法的可能性?

创建零参数的构造函数不是解决方案。

注意: 想要更改A类的任何部分。我问的是,如果不在A类中添加或更改任何内容,是否可以执行此测试。

3 个答案:

答案 0 :(得分:5)

您可以在不调用Mockito构造函数的情况下测试A类。不确定我是否真的了解您的要求,但以下代码对我有用。

import org.junit.Test;
import org.springframework.test.util.ReflectionTestUtils;

import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class ATest {

    @Test
    public void test() {
        A a = mock(A.class);
        when(a.someMethod()).thenCallRealMethod();
        List<String> listInA = new ArrayList<String>();
        ReflectionTestUtils.setField(a, "list", listInA);
        assertThat(a.someMethod(), is(listInA));
    }
}

答案 1 :(得分:4)

你应该把合作者嘲笑到你的班级 - 这意味着你可以创建一个被测试的类的实例,并传入模拟,配置为做正确的事情&#39;什么时候调用它的方法。

在您的示例中,您想要创建一个模拟B,并像这样使用它:

@RunWith(MockitoJUnitRunner.class)
class myTest {
  @Mock private B b;

  public void someMethod() {
    doReturn(new ArrayList<String>()).when(b).getList();
    A a = new A(b);
    assertEquals("result", a.someMethod().get(0));
  }
}

答案 2 :(得分:-2)

  

我不想创建B类对象

添加一个不需要B的构造函数或工厂方法。

public A(B b){
    this(b.getList());
}

/* package local */ A(List<String> list){
    this.list = list;
}

通过使构造函数包为local,可以通过同一个包中的单元测试来访问它。

  

如何在不调用A的构造函数的情况下测试someMethod?

您可以使用

A a = theUnsafe.allocateInstance(A.class);

但不建议这样做,除非您没有其他选择,例如反序列化。