为什么我的存根方法返回 null?

Why is my stubbed method returning null?

我有一个classDummy。我注入了 3 个变量。但是,其中一个是不可注入的,因为它是一个接口。所以我注入了一个对象,其中一个方法 return 是所需的类型。

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

HelperClasssomefunction return 是 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为空。我做错了什么?

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

出于这个原因(和 other reasons), I recommend not using @InjectMocks at all; just build your SUT class 在 @Before 方法中使用真正的构造函数。

当您向测试添加一些打印语句时,此顺序很明显 class。我删除了所有 Class1Class2 的内容,因为它们不相关。请参阅此代码 运行:

@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() return 成为模拟而不是 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 return null 以外的东西是部分模仿,因此他们不会喜欢它。