【问题标题】:Mockito mocked object passed to child class not being used in super传递给子类的 Mockito 模拟对象未在 super 中使用
【发布时间】:2021-03-09 06:26:48
【问题描述】:

我正在尝试模拟身份验证并在实例化子类时传递模拟对象

GoogleOAuthService mockGoogleOAuthService = Mockito.mock(GoogleOAuthService.class);
mockGoogleOAuthService = Mockito.spy(mockGoogleOAuthService);
GoogleCredentials mockGoogleCredentials = Mockito.mock(GoogleCredentials.class);
mockGoogleCredentials = Mockito.spy(mockGoogleCredentials);
Mockito.when(mockGoogleOAuthService.authenticateServiceAccount(secretJson, SERVICE_ACCOUNT_SCOPES)).thenReturn(mockGoogleCredentials);
final HotelViewTpaReportService hotelViewTpaReportService =
        new HotelViewTpaReportService(mockGoogleOAuthService, dr);

HotelViewTpaReportService 的构造函数调用superpublic HotelViewTpaReportService(GoogleOAuthService googleOAuthService, DownloadRequest downloadRequest) throws Exception { super(googleOAuthService, downloadRequest);

然后超类构造函数尝试验证googleOAuthService.authenticateServiceAccount。此时它应该返回模拟的mockGoogleCredentials,因为我们已经写了Mockito.when(mockGoogleOAuthService.authenticateServiceAccount(secretJson, SERVICE_ACCOUNT_SCOPES)).thenReturn(mockGoogleCredentials);。但它没有并尝试进行身份验证。

// Super Class Constructor
public AbstractTpaReportService(GoogleOAuthService googleOAuthService, DownloadRequest downloadRequest) throws Exception {
    this.downloadRequest = downloadRequest;

    this.tpaReportConfig = new TPAReportConfig(downloadRequest);

    final byte[] secretJson = Base64.getDecoder().decode(getRequiredOption(downloadRequest, "secretJson"));

    this.googleCredentials = googleOAuthService.authenticateServiceAccount(secretJson, SERVICE_ACCOUNT_SCOPES);
}

我是 Java 新手,从 python 和 nodejs 迁移过来。

感谢任何帮助。

【问题讨论】:

    标签: java mockito


    【解决方案1】:

    在 Mockito 中存在不同类型的模拟/存根对象:

    Mockito 的模拟对象

    Baeldung上的教程:Mockito - Using Spies, 5. Mock vs Spy,简要区分两者:

    • Mock:无行为对象,大多返回null、empty或false

      当 Mockito 创建一个模拟时——它是从一个类型的类中创建的,而不是从实际实例中创建的。 mock 只是简单地创建了 Class 的基本 shell 实例,完全用于跟踪与它的交互。

    • Spy:使用现有行为的对象,主要用于验证

      另一方面,spy 将包装现有实例。它仍然会以与普通实例相同的方式运行——唯一的区别是它还将被检测为跟踪与它的所有交互。

    仅使用模拟

    有几件事,你应该做不同的更简单的事情:

    • 您已经创建了Mock 对象。不要用Spy 对象覆盖它们。
    • 在定义模拟返回时使用any(),更好地键入ArgumentMatchers.any(Your.class) 或类似于argument-matcher
    // Arrange
      GoogleOAuthService mockAuthService = Mockito.mock(GoogleOAuthService.class);
      // mockGoogleOAuthService = Mockito.spy(mockGoogleOAuthService);
    
      GoogleCredentials mockCredentials = Mockito.mock(GoogleCredentials.class);
      // mockGoogleCredentials = Mockito.spy(mockGoogleCredentials);
    
      // defining a mocked response, using `any()` as argument-matcher
      Mockito.when(mockService.authenticateServiceAccount(any(), any()).thenReturn(mockCredentials);
    
      // injecting the mock
      final HotelViewTpaReportService hotelViewTpaReportService =
     new HotelViewTpaReportService(mockAuthService, dr);
    
    // Act
    

    高级 Mockito 用法

    由于使用 mock 应该可以简化您的测试代码,因此使用 Mockito(在 JUnit 中)测试还有更优雅或更符合思想的方式 - 将其与“pythonic”进行比较:

    • 使用注解@Mock@Spy@InjectMocks)来声明和实例化以及注入模拟
    • 使用 static imports 以最易读的方式缩短 Mockito 辅助方法的使用时间

    您的代码可能如下所示:

    // import some useful static methods
    import static org.mockito.Mockito.doThrow;
    import static org.mockito.Mockito.mock;
    import static org.mockito.Mockito.verify;
    import static org.mockito.Mockito.when;
    import static org.mockito.Matchers.any;
    import static org.mockito.Matchers.anyString;
    
    class MyTest {
    
      // first creating the mocks
      @Mock
      final GoogleOAuthService mockAuthService;
      @Mock
      final GoogleCredentials mockCredentials
      
      // then injecting the mocks
      @InjectMocks
      final HotelViewTpaReportService hotelViewTpaReportService;
    
      @BeforeEach
      public void beforeEach() {
        MockitoAnnotations.initMocks(this);
        // could also define mock-behavior here, using `when(mockedObject. ..)`
      }
    
      @Test
      public void testAuthentication() {
        // Arrange
        // defining a mocked response specific for your test
        when(mockService.authenticateServiceAccount(any(), any()).thenReturn(mockCredentials);
    
        // Act
        // ... your code here
    
        // Assert
        // ... your code here
      }
    

    另见:

    【讨论】:

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