【问题标题】:Mocking ReentrantReadWriteLock in JUnit with mockito使用 mockito 在 JUnit 中模拟 ReentrantReadWriteLock
【发布时间】:2018-07-31 14:10:38
【问题描述】:

在我的实现类中,我有一个读写锁定义如下,

@Inject
@Named("CustomizedLock")
private ReentrantReadWriteLock rwLock;

我在一个名为run()的方法中使用它,

rwLock.writeLock().lock();

锁定进程。但是,当我尝试使用 mockito 进行测试时,我发现 ReentrantReadWriteLock 已初始化。但是当我尝试获取rwLock.writeLock() 时,它是空的。这是我的测试。

@Mock
private ReentrantReadWriteLock feedReadWriteLock;

@InjectMocks
private CustomModule module = mock(CustomModule.class);

/////////////////////////

@Test
public void test() {
    when(module.getReadWriteLock()).thenReturn(mock(ReentrantReadWriteLock.class));
    PowerMockito.doReturn(new ReentrantReadWriteLock()).when(module.getReadWriteLock());
    cacheJob.run();
}

正如我所说,rwLock.writeLock() 为空,但 rwLock 已初始化。请解释一下mockito是如何发生的。理想的方法是什么?

【问题讨论】:

    标签: java unit-testing junit mockito powermockito


    【解决方案1】:

    你说错了:

    @Mock
    private ReentrantReadWriteLock feedReadWriteLock;
    

    上述创建一个模拟,然后你必须以某种方式进入你的被测类

    但是这个:

    @InjectMocks
    private CustomModule module = mock(CustomModule.class);
    

    是假的。 InjectMocks 注释的存在是为了为您完成“进入”部分。

    换句话说,你应该这样做:

    @Mock
    private ReentrantReadWriteLock feedReadWriteLock;
    
    @InjectMocks
    private CustomModule module = new CustomModule();
    

    例如。换句话说:你 模拟你的测试类的实例。您创建一个“真实”实例 - 然后您必须将所需的模拟对象“插入”到该真实实例中嘲笑被测类绝对没有意义。因为您想测试您的代码,而不是模拟框架为您模拟的代码。

    InjectMocks 注释试图为您做到这一点(使用反射和各种黑魔法)。不幸的是,当它无法完成工作时,它就会默默地失败。

    从这个意义上说,答案是:不要只是盲目地使用东西。您必须完全理解您写下的每一行代码。因此:阅读this 以了解这些注释之间的区别。

    仅作记录:请注意,您还必须使用 Mockito JUnitRunner 或手动调用 Mockito.initMocks() 才能让注释发挥作用。

    【讨论】:

      【解决方案2】:

      如果你想模拟被测类,你应该使用@Spy

      @RunWith(MockitoJUnitRunner.class)
      public class CustomModuleTest {
          @Mock
          private ReentrantReadWriteLock feedReadWriteLock;
      
          @Spy
          @InjectMocks
          private CustomModule module;
      
          @Test
          public void test() {
              doReturn(feedReadWriteLock).when(module).getReadWriteLock();
              cacheJob.run();
          }
      }
      

      请注意,spy 的语法与 mock 的语法有些不同。 spy 允许您实例化真实对象,但可以根据需要模拟一些方法。

      这里,我返回feedReadWriteLock,用@Mock注解,这样你也许可以改变它的行为。您不想像在示例中那样返回一个新实例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多