0

Original Scala Code, the method in the XYZ class and OauthProvider:

Here we are trying to test a static method. At first, you may see the original code and then you can see that how I have written the Test class. However after writing the test class using PowerMockito, I am getting error which I have mentioned in detail below. Also I got to know that from Mockito 3.4.0 version onwards, Mockito supports mocking static methods. So I have tried to mock the static method "createFromContext" using Mockito 3.4.0 version, but there also I am getting error. I have given all the details below. Could you please have a look and suggest something so that I can successfully test the method "createFromContext".

object XYZTransformation extends TransformationBase {
  override def processEtl(implicit
      context: TransformContext,
      migrationManager: MigrationManager,
      dataWriter: DataWriter,
      taskExecutor: TaskExecutor,
      loadStrategy: LoadStrategy): Unit = {

    import spark.implicits._

    **val oauthProvider =
      OauthProvider.createFromContext(context, Constants.OAUTH_SECRET_ID)**

//Rest of the code
}

and the code in OAuthProvider class whose static method createFromContext is called from XYZTransformation:

trait OauthProvider {
  def getOauthCredentials: OauthConfig
}

object OauthProvider {
  def createFromParams(params: Map[String, String], argumentName: String): OauthProvider = {
    params.get(argumentName) match {
      case Some(secretId) =>
        OauthSecretConfigProvider(
          secretId,
          params.getOrElse(
            Constants.OCI_CONFIG_PATH,
            oci.Constants.OCI_LOCAL_CONFIG_PATH),
          params.getOrElse(
            Constants.OCI_CONFIG_PROFILE,
            oci.Constants.OCI_LOCAL_PROFILE))

      case None
          if params.contains(Constants.OAUTH_BEARER_TOKEN) || params.contains(
            Constants.OAUTH_CONSUMER_KEY) =>
        OauthLocalConfigProvider(
          params.getOrElse(Constants.OAUTH_CONSUMER_KEY, ""),
          params.getOrElse(Constants.OAUTH_CONSUMER_SECRET, ""),
          params.getOrElse(Constants.OAUTH_ACCESS_TOKEN_URL, ""),
          params.getOrElse(Constants.OAUTH_BEARER_TOKEN, ""))
      case _ =>
        throw new IllegalArgumentException(
          "Invalid Oauth Configuration provided")
    }
  }
}

In the below test class we are trying to test,static method - "createFromContext" of OauthProvider class in the above code of XYZTransformation.

Test Class(Using ScalaTest and PowerMockito):

@RunWith(classOf[PowerMockRunner])
@PrepareForTest(Array(classOf[OauthProvider]))  // Ensure PowerMock can modify OauthProvider
class XYZTransformationTest extends AnyFunSuite with MockitoSugar {

  test("Mock OauthProvider.createFromContext") {
    // Step 1: Create a mock instance of OauthProvider
    val mockOauthProvider = mock[OauthProvider]

    // Step 2: Mock static method using PowerMockito
    PowerMockito.mockStatic(classOf[OauthProvider])

    // Step 3: Define behavior for createFromContext
    PowerMockito
      .when(OauthProvider.createFromContext(any[TransformContext], any[String]))
      .thenReturn(mockOauthProvider)

    // Step 4: Use the mock in test
    val context = mock[TransformContext]
    val result = OauthProvider.createFromContext(context, Constants.OAUTH_SECRET_ID)

    assert(result == mockOauthProvider) // Validate that our mock is returned
  }
}

We are facing the error:

[Ljava.lang.Object;@405325cf The class com.oracle.health.analytics.transformations.utils.oauth.OauthProvider not prepared for test. org.powermock.api.mockito.ClassNotPreparedException:

The things that we have tried:

We have gone through the similar errors in Stack overflow and tried them, but the issue is not solved.We tried to extend PowerMockTestCase, but sice we are already extending AnyFunSuite, so we again faced different error, naturally, as we replaced AnyFunSuite with PowerMockTestCase like below, but we cannot extend 2 classes simutaneously in Scala/Java, right?

class XYZTransformationTest extends PowerMockTestCase with MockitoSugar {
//Code
}
  1. We got to know that from Mockito 3.4.0 version we can mock static methods - as per point #48 in the link

So we tried to mock using Mockito 3.4.0 version following the pattern given in the javadoc, point number 48 in the javadoc page

class XYZTransformationTest extends AnyFunSuite with MockitoSugar {

  test("Mock OauthProvider.createFromContext using Mockito.mockStatic") {
    val mockContext = mock[TransformContext] 
    val mockOauthProvider = mock[OauthProvider] 
    val mockedStatic: MockedStatic[OauthProvider] = mockStatic(classOf[OauthProvider])
    
    try {
      // Step 4: Define behavior for createFromContext (NO ANY[])
      mockedStatic.when(() => OauthProvider.createFromContext(mockContext, Constants.OAUTH_SECRET_ID))
        .thenReturn(mockOauthProvider) 

      val result = OauthProvider.createFromContext(mockContext, Constants.OAUTH_SECRET_ID)

      assert(result == mockOauthProvider)

      mockedStatic.verify(() => OauthProvider.createFromContext(mockContext, Constants.OAUTH_SECRET_ID))
    } finally {
      mockedStatic.close() // Ensures static mock does not leak into other tests
    }
  }
}

This time we get error:

OauthProvider$MockitoMock$1099687121 cannot be returned by params() params() should return Map

If you're unsure why you're getting above error read on. Due to the nature of the syntax above problem might occur because:

  1. This exception might occur in wrongly written multi-threaded tests. Please refer to Mockito FAQ on limitations of concurrency testing.
  2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
    • with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.

Could someone please suggest how to overcome these errors?

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.