1

I am trying to mock authentication and pass the mocked object while instantiating the child class

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);

Where the constructor of HotelViewTpaReportService calls super i.e public HotelViewTpaReportService(GoogleOAuthService googleOAuthService, DownloadRequest downloadRequest) throws Exception { super(googleOAuthService, downloadRequest);

And super class constructor then tries to authenticate googleOAuthService.authenticateServiceAccount. It should at this point return the mocked mockGoogleCredentials since we have written Mockito.when(mockGoogleOAuthService.authenticateServiceAccount(secretJson, SERVICE_ACCOUNT_SCOPES)).thenReturn(mockGoogleCredentials);. But it doesn't and tries authenticating.

// 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);
}

I am fairly new to Java , having migrated from python and nodejs.

Any help is appreciated.

Akshay Hazari
  • 3,186
  • 4
  • 48
  • 84

1 Answers1

3

In Mockito there exist different types of mock/stub objects:

Mockito's mocking objects

The tutorial on Baeldung: Mockito - Using Spies, 5. Mock vs Spy, differentiates the two briefly:

  • Mock: no behavior object, mostly returning null, empty or false

    When Mockito creates a mock – it does so from the Class of a Type, not from an actual instance. The mock simply creates a bare-bones shell instance of the Class, entirely instrumented to track interactions with it.

  • Spy: object using existing behavior, mainly for verification

    On the other hand, the spy will wrap an existing instance. It will still behave in the same way as the normal instance – the only difference is that it will also be instrumented to track all the interactions with it.

Use only Mock

There are a few things, you should do different & simpler:

  • You have already created Mock objects. Don't overwrite them with Spy objects.
  • Use any(), better typed ArgumentMatchers.any(Your.class) or similar as argument-matcher when defining the mocked return
// 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

Advanced Mockito usage

Since using mocks should simplify your test code, there are even more elegant or ideomatic ways using Mockito (in JUnit-) tests - compare it to "pythonic":

  • use annotations (@Mock, @Spy, @InjectMocks) to declare & instantiate plus inject mocks
  • use static imports to shorten usage of Mockito's helper-methods in most readable way

Your code could look like:

// 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
  }

See also:

hc_dev
  • 8,389
  • 1
  • 26
  • 38