java – 为什么我的stubbed方法返回null?

我有一个班级假人.我注入3个变量.但是,其中一个不能注射,因为它是一个界面.所以我注入一个对象,其中一个方法返回所需的类型.

Class Dummy
{
   private final Class1 class1;
   private final Class2 class2
   private final Interface1 interface1;

  @Inject
  Dummy(Class1 class1, Class2 class2, HelperClass helperclass) 
  {
       this.class1 = class1;
       this.class2 = class2;
       this.interface1 = helperclass.somefunction();
  }
}

HelperClass的somefunction返回Interface1的一个实例.

这是我的测试:

@RunWith(MockitoJUnitRunner.class)
Class DummyTest 
{
  @Mock 
  private Class1 class1;

  @Mock
  private Class2 class2;

  @Mock
  private HelperClass helperclass;

  @InjectMocks
  private Dummy dummy;

  @Before
  public void start() 
  {
    Interface1 mockInterface = mock(Interface1.class);
    when(helperclass.somefunction()).thenReturn(mockInterface);
  }
  @Test
  public void test()
  {
   // etc...
  }
}

但是,当我运行测试时,interface1为null.我究竟做错了什么?

解决方法:

@InjectMocks发生在@Before注释之前.

出于这个原因(和other reasons),我建议不要使用@InjectMocks;用真正的构造函数在@Before方法中构建你的SUT类.

当您向测试类添加一些print语句时,这种排序很明显.我删除了所有Class1和Class2的东西,因为它不相关.看到这个代码运行:

@RunWith(MockitoJUnitRunner.class)
public class DummyTest {
  @Mock
  private HelperClass helperclass;

  @InjectMocks
  private Dummy dummy;

  @Before
  public void start() 
  {
    System.out.println("In @Before!");
    Interface1 mockInterface = mock(Interface1.class);
    when(helperclass.somefunction()).thenReturn(mockInterface);
  }

  @Test
  public void test()
  {
    System.out.println("In @Test!");
  }

  public static class Dummy {
    public final Interface1 interface1;
    public final HelperClass helperclass;

   @Inject
   Dummy(HelperClass helperclass) 
   {
     System.out.println("In dummy constructor!");
        this.interface1 = helperclass.somefunction();
        this.helperclass = helperclass;
   }
 }

  private static class HelperClass {
    Interface1 somefunction() {
      return new Interface1() {};
    }
  }

  private static interface Interface1 {

  }
}

输出:

In dummy constructor!
In @Before!
In @Test!

如果您坚持使用@Mock和@InjectMocks,您可以尝试使用answer参数:

@Mock(answer=Answers.RETURNS_MOCKS)

将使helperclass.somemethod()返回一个mock而不是null.

老实说,它以这种方式工作并不奇怪. Mockito的作者真的不喜欢Partial Mocks / Stubs,并且明确地这样说in their documentation

As usual you are going to read the partial mock warning: Object oriented programming is more less tackling complexity by dividing the complexity into separate, specific, SRPy objects. How does partial mock fit into this paradigm? Well, it just doesn’t… Partial mock usually means that the complexity has been moved to a different method on the same object. In most cases, this is not the way you want to design your application.

However, there are rare cases when partial mocks come handy: dealing with code you cannot change easily (3rd party interfaces, interim refactoring of legacy code etc.) However, I wouldn’t use partial mocks for new, test-driven & well-designed code.

让helperclass返回null以外的东西是部分mock,因此他们不喜欢它.

上一篇:RPC架构简介与原理


下一篇:stub和mock