Mockito - thenReturn始终返回空对象

vu8f3i0k  于 2022-11-08  发布在  其他
关注(0)|答案(8)|浏览(282)

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

  • 切:*
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;
  }

}
  • Spring配置:*
<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对象在上面的CUT中标记为//PROBLEM的行上为空。我希望用我的测试方法中的“invalidServiceResponse”对象填充该对象。从我的System.out.println的输出来看,我的bpRequestVO在内容上与我的someBPRequestVO匹配。
有人能告诉我我错过了什么吗?
感谢您抽出宝贵时间!

62lalag4

62lalag41#

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

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

u7up0aaq2#

when()一起使用的BPRequestVO示例与getTestData()中使用的BPRequestVO示例不同。
除非您覆写equals(),否则它们不会相符。
如果重写equals(),则不需要编写自定义Matcher。请注意Mockito documentation中的以下内容:
“自定义参数匹配器会使测试可读性降低。有时候,最好为传递给模拟的参数实现equals()(Mockito自然使用equals()进行参数匹配)。这样可以使测试更清晰。”

1cosmwyk

1cosmwyk3#

问题出在您对when()的使用上。
您提交了对构造示例的引用;因此,只有当传递给方法的参数是 * 相同的引用 * 时,模拟才会返回您想要的结果。
您需要的是一个参数匹配器;类似于:

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

当然,它要求您编写参数匹配器!
请注意,有一个内置的匹配器可以做你想做的:

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

当然,这个匹配器要求您的BPRequestVO类实现equals()(以及hashCode())!

knpiaxh1

knpiaxh14#

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

vx6bjr1n

vx6bjr1n5#

用于模拟的BPRequestVO对象示例与执行junit时使用的示例不同。
最好的方法是在模拟时配置对象的任何示例

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

可更新为

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

0s7z1bwu6#

我的问题是传递空值,因为方法参数与我设置的when()子句不符。
例如:

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

这将失败。

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

这就过去了。

iq0todco

iq0todco7#

我的问题是服务的示例,它是自动连接的/mockbean在Test-〉given()部分有不同的示例,在执行时有不同的示例。
这是通过在调试模式下运行测试并检查模拟存根和执行代码中的每个值而发现的。如果所有参数和模拟示例都相同,则只有thenReturn()将返回预期值。
在myscenario中,类的模拟示例有多个实现,通过添加@限定符(“name”),示例在给定()和实际执行中变得相同。

5lhxktic

5lhxktic8#

在多线程的情况下也可能发生这种情况。mockito在@Test方法返回后重置了被模拟对象的处理程序,而某个地方(另一个线程)仍在使用被模拟对象。
对于线程池提供线程的情况,可以模拟一个线程池代替,在当前线程中执行Runner.run()被证明是有效的。

相关问题