【问题标题】:Java Mockito - How to test a method which is calling a method in the same class as well as a method from other class?Java Mockito - 如何测试调用同一类中的方法以及其他类中的方法的方法?
【发布时间】:2016-06-10 09:58:28
【问题描述】:

我有这样的代码结构。 ClassA 中的方法methodToTest 正在调用ClassA 中的方法以及ClassB 中的方法

public class ClassA {
    @Autowired
    ClassB classB;

    public void methodToTest() {
        Object c = methodInA();
        Object d = classB.methodInB(c);
    }

    public Object methodInA() {
        //do something
    }
}

public class ClassB {
    public Object methodInB(Object obj) {
        //do something
    }
}

我试图模拟两个调用,即调用methodInAmethodInB

以下是单元测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class ClassATest {
    @InjectMocks
    ClassA classA;

    @Mock
    ClassB classB;

    @Spy
    ClassA classASpy;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    //Test method in ClassA
    @Test
    public void testMethodInA() {
        Object mockObjA = mock(Object.class);
        Object mockObjB = mock(Object.class);

        doReturn(mockObjA).when(classASpy).methodInA();
        when(classB.methodInB(mockObjA)).thenReturn(mockObjB);

        classA.methodToTest();

        //assertions
    }

}

在运行测试时,Object c 为空,但我希望它等于 mockObjA

我也从测试中尝试使用classASpy.methodToTest() 进行调用。但随后它在Object d = classB.methodInB(c)methodToTest() 中给出NullPointerException

测试这种情况的正确方法是什么?

【问题讨论】:

  • 使用 Mockito 注释需要 Mockito 运行器或适当的规则或 initMocks 调用,请参阅文档:site.mockito.org/mockito/docs/current/org/mockito/…
  • 我已经更新了测试代码。我在设置方法中使用 initMocks。我错过了在这里提及它。
  • 你能发一个minimal reproducible example吗?
  • methodInA写一个测试,然后为methodToTest写一个测试,不用担心methodInA

标签: unit-testing junit mocking mockito spy


【解决方案1】:

当您调用methodToTest 时,您正在测试单元ClassA。通过模拟该单元的某些内容来更改被测单元没有多大意义。因为那样你会测试一些与ClassA完全不同的东西。

您应该做的是测试classB.methodInB 是否使用正确的参数调用。为此,您可以使用 ArgumentCaptor 作为调用参数 classB.methodInB

ArgumentCaptor<Object > argument = ArgumentCaptor.forClass(Object .class);
verify(mockObjB).methodInB(argument.capture());
Object capturedArgument = argument.getValue();

然后您对capturedArgument 进行断言,以验证ClassA.methodInA 是否正常工作。

【讨论】:

  • 但是我将不得不模拟在methodInA()中调用的所有外部方法调用,在每个使用methodInA()的方法的测试中
  • @msfk 如果methodInA 真的那么复杂,那么ClassA 可能不遵守单一职责原则。如果是这种情况,将methodnInA 提取到它自己的接口可能是有意义的。然后你也可以模拟对methodInA的调用。
  • 我从实际类中分离出一个辅助类,并将方法作为公共移动到辅助类。这是一个好习惯吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多