如何使用Mockito在模拟上显示所有调用

时间:2014-06-18 20:14:10

标签: java unit-testing debugging junit mockito

我的单元测试失败了,我不确定原因。我希望能够看到在被测系统中发生的模拟上的所有调用。这不是我想要的所有测试的行为,只是为了我需要快速调整以便能够找出错误的测试。

然而,它似乎有点像黑客。 是否可以在Mockito中本地执行此操作,而无需使用Thread.currentThread().getStackTrace()

这不是首选,因为堆栈跟踪包括Mockito内部使用的所有其他调用。

3 个答案:

答案 0 :(得分:43)

此功能自Mockito 1.9.5开始构建。只需使用

mock(ClassToMock.class, withSettings().verboseLogging())

答案 1 :(得分:2)

在Mockito 1.9.5中,您可以使用MockingDetails Mockito.mockingDetails(Object mockToInspect)检查模拟。

您可以通过调用MockingDetailsgetMock()getStubbings()等来挖掘getInvocations()属性,等等……或仅使用printInvocations()返回的方法:

  

该模拟发生的调用的打印友好列表   宾语。此外,此方法还会打印存根信息,   包括未使用的存根。有关未使用的存根的更多信息   检测请参见MockitoHint。

例如,在JUnit 5中:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.Mock;
import org.mockito.Mockito;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
public class FooTest {

    Foo foo;

    @Mock
    Bar bar;

    @Test
    void doThat() throws Exception {

        Mockito.when(bar.getValue())
               .thenReturn(1000L);          

        // ACTION
        foo.doThat();

        // ASSERTION
        // ...

        // add that to debug the bar mock           
        System.out.println(mockingDetails(bar).printInvocations());
    }
}

然后您将得到如下输出:

[Mockito] Interactions of: Mock for Bar, hashCode: 962287291
 1. bar.getValue();
  -> at Foo.doThat() (Foo.java:15) 
   - stubbed -> at FooTest.doThat(FooTest.java:18)

请注意,输出中带有参考行的类是指向源代码/测试类的链接。很实用。

答案 2 :(得分:0)

我能够确定 使用Thread.currentThread().getStackTrace()的方法,并循环遍历这些元素。这很丑陋,但确实可以完成这项任务。我希望另一位回答者能有更好的方法。

  1. 创建一个InvocationListener,并将其传递给受测试系统的类名。
  2. 将听众传递到Mockito.withSettings().invocationListeners()
  3. 暂时修改测试以使用此MockSettings对象创建模拟。
  4. InvocationListener的代码:

    public static class DebugInvocationListener implements
            InvocationListener {
        private final String className;
    
        public DebugInvocationListener(Class<?> klass) {
            this(klass.getName());
        }
    
        public DebugInvocationListener(String className) {
            this.className = className;
        }
    
        @Override
        public void reportInvocation(MethodInvocationReport report) {
            System.out.println(report.getInvocation());
            StackTraceElement[] trace = Thread.currentThread().getStackTrace();
            for(StackTraceElement element : trace) {
                if(element.getClassName().equals(className)) {
                    System.out.println(element);
                    System.out.println();
                    break;
                }
            }
        }
    }