【问题标题】:Mockito - thenReturn always returns null objectMockito - thenReturn 总是返回空对象
【发布时间】:2014-12-28 03:04:26
【问题描述】:

我正在尝试实现 Mockito 来测试特定方法,但 .thenReturn(...) 似乎总是返回一个空对象,而不是我想要的:

剪切:

public class TestClassFacade {

  // injected via Spring
  private InterfaceBP bpService;

  public void setBpService(InterfaceBP bpService) {

      this.bpService = bpService;
  }

  public TestVO getTestData(String testString) throws Exception {

    BPRequestVO bpRequestVO = new BPRequestVO();

    bpRequestVO.setGroupNumber(testString) ;
    bpRequestVO.setProductType("ALL") ;           
    bpRequestVO.setProfileType("Required - TEST") ;

    IBPServiceResponse serviceResponse = bpService.getProduct(bpRequestVO);  //PROBLEM

    if (serviceResponse.getMessage().equalsIgnoreCase("BOB")) {

        throw new Exception();

    } else {

        TestVO testVO = new TestVO();
    }

    return testVO;
  }

}

弹簧配置:

<bean id="testClass" class="com.foo.TestClassFacade">

   <property name="bpService" ref="bpService" />

</bean>

<bean id="bpService" class="class.cloud.BPService" />

Mockito 测试方法:

@RunWith(MockitoJUnitRunner.class)
public class BaseTest {

    @Mock BPService mockBPService;
    @InjectMocks TestClassFacade mockTestClassFacade;

    private String testString = null;
    private BPRequestVO someBPRequestVO = new BPRequestVO();
    private IBPServiceResponse invalidServiceResponse = new BPServiceResponse();

    @Test (expected = Exception.class)
    public void getBPData_bobStatusCode_shouldThrowException() throws Exception {

        invalidServiceResponse.setMessage("BOB");

        someBPRequestVO.setGroupNumber(null);
        someBPRequestVO.setProductType("ALL");
        someBPRequestVO.setProfileType("Required - TEST");

        System.out.println("1: " + someBPRequestVO.getGroupNumber());
        System.out.println("2: " + someBPRequestVO.getProductType());
        System.out.println("3: " + someBPRequestVO.getProfileType());
        System.out.println("4: " + someBPRequestVO.getEffectiveDate());

        when(mockBPService.getProduct(someBPRequestVO)).thenReturn(invalidServiceResponse);

        mockTestClassFacade.getTestData(testString);

        verify(mockBPService).getProduct(someBPRequestVO);
    }
}

系统输出:

1: null
2: ALL
3: Required - TEST
4: null

这里发生的情况是,当我运行测试时,serviceResponse 对象在上面标有 //PROBLEM 的 CUT 行上为空。我的愿望是用我的测试方法中的“invalidServiceResponse”对象填充该对象。从我的 System.out.println 的输出来看,我的 bpRequestVO 在内容上似乎与我的 someBPRequestVO 匹配。

谁能告诉我我在这里缺少什么?

感谢您的宝贵时间!

【问题讨论】:

  • 它很可能无法将参数与您在 when(...) 中设置的 getProduct 与实际方法中传递的内容相匹配。尝试在 when(service.getProduct(argThat(...)).thenReturn 中使用匹配器。
  • OP:你应该接受@lewthor的回答;我弄错了,覆盖.equals() 就足够了,你不需要参数匹配器
  • 感谢 fge 的跟进...我刚刚仅使用 .equals() 对其进行了测试,然后返回此页面以确保我没有误解某些内容。果然我找到了你的评论!我已经切换了接受的答案。谢谢你的诚实。

标签: java null mockito


【解决方案1】:

您可以使用“any(YourObject.class)”创建一个模拟参数,而不是在您的 BPRequestVO 类中创建一个等于方法,如下所示:

when(mockBPService.getProduct(any(BPRequestVO.class))).thenReturn(invalidServiceResponse);

【讨论】:

  • any(YourObject.class) 就是答案。不知道为什么其他帖子比自己聪明。点赞
【解决方案2】:

when() 一起使用的BPRequestVO 实例与getTestData() 中使用的实例不同。
除非您覆盖 equals(),否则它们将不匹配。

如果你重写 equals(),你应该不需要编写自定义 Matcher。请注意Mockito documentation 中的以下内容:

“自定义参数匹配器会使测试的可读性降低。有时最好为传递给 mock 的参数实现 equals()(Mockito 自然使用 equals() 进行参数匹配)。这可以使测试更清晰。”

【讨论】:

  • 谢谢lewhor!我在 BPRequestVO 中添加了 .equals()(和 .hashcode),当我运行我的测试用例时,我现在在我的 CUT 中看到了一个填充的 serviceResponse 对象。
【解决方案3】:

问题在于您对when()的使用。

您提交对构造实例的引用;因此,只有当传递给方法的参数是相同的引用时,模拟才会返回你想要的。

你想要的是一个参数匹配器;类似:

when(mockBPService.getProduct(argThatMatches(someBPRequestVO))
    .thenReturn(whatYouWant);

当然,这需要你编写参数匹配器!

请注意,有一个内置的匹配器可以做你想做的事:

when(mockBPService.getProduct(eq(someBPRequestVO))).thenReturn(whatYouWant);

这个匹配器当然需要你的 BPRequestVO 类实现 equals()(和 hashCode() 也是)!

【讨论】:

    【解决方案4】:

    我的问题是模拟服务被定义为最终服务。

    【讨论】:

      【解决方案5】:

      用于模拟的 BPRequestVO 对象实例与 junit 执行时使用的实例不同。

      最好的方法是在模拟时配置对象的任何实例

      when(mockBPService.getProduct(someBPRequestVO)).thenReturn(invalidServiceResponse);
      

      可以更新

      when(mockBPService.getProduct(Mockito.any(BPRequestVO.class))).thenReturn(invalidServiceResponse);
      

      【讨论】:

        【解决方案6】:

        我的问题是传递 null 作为方法参数与我设置的 when() 子句不匹配。

        例如

        Car car = mock(Car.class)
        when(car.start(anyString()).thenReturn("vroom");
        assertEquals("vroom", car.start(null));
        

        这会失败。

        assertEquals("vroom", car.start("Now"));
        

        通过了。

        【讨论】:

          【解决方案7】:

          我的问题是自动装配的服务实例/mockbean 在 Test->given() 部分有不同的实例,而在执行时它有不同的实例。

          这是通过在调试模式下运行测试并检查模拟存根和执行代码中的每个值而发现的。如果所有参数和模拟实例都相同,则只有 thenReturn() 会返回预期值。

          在 myscenario 中,该类的模拟实例具有多个实现,并且通过添加 @Qualifier("name") 实例在 given() 和实际执行中变得相同。

          【讨论】:

            猜你喜欢
            • 2022-12-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-02-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多