简体   繁体   English

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

[英]Is it possible to invoke mocked object's method?

I have, for example, this class: 例如,我有此类:

public class A {
    private List<String> list;

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

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

I want to unit test someMethod without invoking constructor. 我想在不调用构造函数的情况下对someMethod进行单元测试。 I use reflection to set list . 我使用反射来设置list

The problem is that I don't want to create B class object and I cannot mock it since it will cause NPE. 问题是我不想创建B类对象,并且无法模拟它,因为它将导致NPE。

So my question is: 所以我的问题是:

How to test someMethod without calling constructor of A ? 如何在不调用A构造函数的情况下测试someMethod Is there any way to mock class A and doesn't lose posibility to call methods? 有什么方法可以模拟类A并且不会失去调用方法的可能性吗?

Creating constructor with zero arguments is not a solution. 用零参数创建构造函数不是解决方案。

Note: I don't want to change any part of A class. 注:不想改变类的任何部分。 I'm asking if it is possible to perform this test without adding or changing anything in A class. 我问是否可以在不添加或更改A类中的任何内容的情况下执行此测试。

You can test class A without calling it's constructor by Mockito. 您可以测试类A而无需Mockito调用它的构造函数。 Not sure if I really understand your requirement but the following codes work for me. 不知道我是否真的了解您的要求,但是以下代码对我有用。

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));
    }
}

You should mock out the collaborators to your class -- that means that you can create an instance of the class being tested, and pass in mocks, configured to 'do the right thing' when it's methods are called. 您应该将协作者模拟到您的类上-这意味着您可以创建要测试的类的实例,并传入模拟,将其配置为在调用方法时“做正确的事”。

In your example, you want to create a mock B, and use it like this: 在您的示例中,您想要创建一个模拟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));
  }
}

I don't want to create B class object 我不想创建B类对象

Add a constructor or factory method which doesn't require a B. 添加不需要B的构造函数或工厂方法。

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

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

By making the constructor package local it can be accessed by unit tests in the same package. 通过将构造函数包放在本地,可以通过同一包中的单元测试进行访问。

How to test someMethod without calling constructor of A? 如何在不调用A的构造函数的情况下测试someMethod?

You can use 您可以使用

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

but this is not recommended unless you have no other option eg deserialization. 除非您没有其他选择(例如反序列化),否则不建议这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM