Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unit Testing with AWS Amplify - Mocking #3641

Open
DigiValetMobiles opened this issue Sep 23, 2024 · 5 comments
Open

Unit Testing with AWS Amplify - Mocking #3641

DigiValetMobiles opened this issue Sep 23, 2024 · 5 comments
Labels
closing soon Issue will auto-close if there is no additional activity within 7 days. pending-community-response Issue is pending response from the issue requestor question General question

Comments

@DigiValetMobiles
Copy link

I'm currently facing challenges in unit testing my authentication functions that utilize the AWS Amplify library, specifically regarding the AWSCognitoAuthSession class. The issue arises because this class has an internal constructor property, making it inaccessible in my test classes.

Service:
aws-auth-cognito

Environment:
SDK Version: 2.20.0

Problem:
I need to test my sign-in function, which uses the Amplify Auth sign-in function and fetches the user session. However, I cannot mock the AWSCognitoAuthSession effectively due to its constructor's visibility constraints.

Questions:
What strategies can I use to mock AWSCognitoAuthSession in my unit tests?
Are there any recommended practices for testing functions that rely on AWS Amplify's Auth module?
Would it be possible to consider making constructors more accessible for testing purposes in future updates?

Testing framework:
JUnit, Mockk

Programming Language:
Kotlin

If there are any specific examples or resources that could help clarify how to effectively test AWS Amplify Auth functionality, I would greatly appreciate it!

@github-actions github-actions bot added pending-triage Issue is pending triage pending-maintainer-response Issue is pending response from an Amplify team member labels Sep 23, 2024
@phantumcode
Copy link
Contributor

@DigiValetMobiles Thanks for submitting the issue. Can you provide additional details on what specific sign in function you're testing and how you've implemented that sign in function?

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending response from an Amplify team member label Sep 23, 2024
@phantumcode phantumcode added question General question pending-maintainer-response Issue is pending response from an Amplify team member labels Sep 23, 2024
@github-actions github-actions bot removed the pending-triage Issue is pending triage label Sep 23, 2024
@DigiValetMobiles
Copy link
Author

Here's a code snippet of my sign-in function:

fun signIn(username: String, password: String) = flow {
    Amplify.Auth.signIn(username = username, password = password)
    val session = Amplify.Auth.fetchAuthSession() as AWSCognitoAuthSession
    emit(DigiAuthResult.Success(session.toDigiAuthResponse()))
}.catch {
    emit(it.toDigiAuthError())
}

I am trying to create a mock object of AWSCognitoAuthSession to test the success scenario of my signIn function using dummy values. However, I'm encountering issues when attempting to mock it like this:

val mockObject = mockk<AWSCognitoAuthSession>(relaxed = true)

It would be helpful if you could provide @VisibleForTesting annotations on any private or internal classes, as this could simplify the mocking process.

Thank you!

@phantumcode
Copy link
Contributor

@DigiValetMobiles making AWSCognitoAuthSession visible for testing isn't a viable option. It would also require other classes it depends on such as AuthSessionResult to be visible for testing.

Looking at your sign-in function, there isn't any business logic involved so I would reconsider what the value of unit testing this function and reconsider it as a integration test instead.

Are you trying to unit test the toDigiAuthResponse()? or are you unit testing the emit logic?

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending response from an Amplify team member label Sep 27, 2024
@DigiValetMobiles
Copy link
Author

Thanks for your feedback! I want to test the toDigiAuthResponse() function along with the emission logic, as it contains all of my business logic that depends on the AWSCognitoAuthSession data. Overall, I’m aiming to write unit tests for the signIn function since it includes crucial business logic. I appreciate your insights on the testing strategy!

@github-actions github-actions bot added the pending-maintainer-response Issue is pending response from an Amplify team member label Oct 15, 2024
@mattcreaser
Copy link
Member

@DigiValetMobiles could you expand on the exact issue you're seeing? The constructor does not need to be accessible to mock with mockk.

As an example, given the following fake production code:

class TestCode {
    suspend fun getSession(): DigiAuthResponse {
        val session = Amplify.Auth.fetchAuthSession() as AWSCognitoAuthSession
        return session.toDigiAuthResponse()
    }
}

data class DigiAuthResponse(
    val isSignedIn: Boolean,
)

fun AWSCognitoAuthSession.toDigiAuthResponse() = DigiAuthResponse(
    isSignedIn = this.isSignedIn
)

I can write a unit test for the getSession function like this:

    @Test
    fun `test that DigiAuthResponse.isSignedIn is true`() = runTest {
        val mockSession = mockk<AWSCognitoAuthSession>{
            every { isSignedIn } returns true
        }

        mockkObject(Amplify) {
            coEvery { Amplify.Auth.fetchAuthSession() } returns mockSession
            val result = TestCode().getSession()
            assertTrue(result.isSignedIn)
        }
    }

Which works just fine even though I cannot instantiate an AWSCognitoAuthSession in this test because of the constructor.

If you can elaborate on where this is going wrong we may be able to point you in the right direction 😄

@github-actions github-actions bot removed the pending-maintainer-response Issue is pending response from an Amplify team member label Oct 21, 2024
@mattcreaser mattcreaser added the pending-community-response Issue is pending response from the issue requestor label Oct 21, 2024
@vincetran vincetran added the closing soon Issue will auto-close if there is no additional activity within 7 days. label Nov 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closing soon Issue will auto-close if there is no additional activity within 7 days. pending-community-response Issue is pending response from the issue requestor question General question
Projects
None yet
Development

No branches or pull requests

4 participants