【问题标题】:Mocking AWS Amplify Auth APIs for Android模拟适用于 Android 的 AWS Amplify Auth API
【发布时间】:2021-06-18 13:21:46
【问题描述】:

我的 Android 应用程序使用 AWS Cognito 和 Amplify Auth SDK 进行身份验证,我正在尝试为登录/注册流程编写 JUnit 测试用例。我正在使用 Mockito 框架来模拟这些类。

我从登录开始,我的登录模型是这样的

class LoginService(val auth: AuthCategory) {

 fun login(username: String, password: String): MutableLiveData<Login> {
    val liveData = MutableLiveData<Login>()
    auth.signIn(username, password,
        { result ->
            liveData.postValue(Login(result, null))
        },
        { error ->
            liveData.postValue(Login(null, error))
        }
    )
    return liveData
    }
  }

我的视图模型这样称呼它

class LoginViewModel : ViewModel() {

    val loginService = LoginService(Amplify.Auth)

    fun login(username: String, password: String): MutableLiveData<Login> {
        return loginService.login(username, password)
    }
}

我的测试用例是这样的

lateinit var auth: AuthCategory
lateinit var loginService: LoginService

@Before
fun onSetup() {
    auth = mock(Amplify.Auth::class.java)
    loginService = LoginService(auth)
}

@Test
fun loginTest() {
    val authSignIn: Consumer<*>? = mock(Consumer::class.java)
    val authEx: Consumer<*> = mock(Consumer::class.java)
    `when`(
        auth.signIn(
            anyString(), anyString(),
            authSignIn as Consumer<AuthSignInResult>, authEx as Consumer<AuthException>
        )
    )
    loginService.login("username", "password").observeForever {
        assertTrue(it.result?.isSignInComplete!!)
    }
}

请帮我验证这种方法, 我正在尝试找到一种方法来触发Auth.signIn() 方法的AuthSignInResultAuthException,以便我会断言登录是否成功或有错误。

我对 AWS Amplify 和 Cognito 环境非常陌生,非常感谢以正确方式执行此操作的建议/参考。提前致谢。

【问题讨论】:

    标签: android mockito amazon-cognito junit4 aws-amplify-sdk-android


    【解决方案1】:

    您可以通过多种方式鼓励使用 Amplify Android 进行可测试性。在以下两种方法中,我肯定从第一种方法开始。

    使用类别接口

    这是一种“单元测试”级别的方法。

    Amplify.Auth 实现了AuthCategoryBehavior 接口。因此,如果您更改所有代码以使用该接口,您可以模拟它。

    假设你有一些使用 Auth 作为依赖的类:

    class YourClass(private val auth: AuthCategoryBehavior = Amplify.Auth) {
        ...
    }
    

    现在,在您的生产代码中,您可以让依赖注入代码执行以下操作:

    1. 初始化 Amplify(使用 addPlugin(AWSCognitoAuthPlugin())Ampify.configure(...) 等)
    2. 接下来,返回一个你的 YourClass 的单例,由 YourClass(auth = Amplify.Auth) 构建

    但是,在您的测试代码中,您可以使用 Amplify Auth 的模拟来构建 YourClass 的实例:

    val mockAuth = mock(AuthCategoryBehavior::class.java)
    val yourClass = YourClass(mockAuth)
    

    这样,您可以指定它在测试条件下的行为方式:

    doAnswer
        { invocation ->
            // Get a handle to the success callback
            val onResult =
                invocation.arguments[2] as Consumer<AuthSignInResult>
            // Invoke it with some canned result
            onResult.accept(mock(AuthSignInResult::class.java))
        }
        .`when`(mockAuth)
        .signIn(eq(username), eq(password), any(), any())
    

    使用 OkHttp 的 MockWebServer

    这更像是一种“组件”或“集成”级别的方法。在这里,我们将使用 MockWebServer 实例从假 Cognito 服务器返回预设响应。

    在此流程中,您将在生产和测试中使用所有真正的 Amplify 库代码。只是让人相信您可以控制 Cognito 对客户的响应。

    为此,您应该在 Android Studio 的网络监视器选项卡中查看实际 HTTP 响应。然后,将该内容安排到下面的测试代码中。

    val mockWebServer = MockWebServer()
    mockWebServer.start(8080);
    val fakeCognitoEndpointUrl = mockWebServer.url("/");
    
    val cookedResponse = new MockResponse()
        .setResponseCode(200)
        .setBody(new JSONObject()
            .put("blah blah", "content you saw in Network Monitor")
            .toString()
        )
    mockWebServer.enqueue(cookedResponse)
    
    // Build up a JSON representation of your `amplifyconfiguration.json`
    // But replace the endpoint URL with mock web server's.
    val json = JSONObject()
        .put(...)
        // Find correct field to populate by
        // viewing structure of amplifyconfiguration.json
        .put("Endpoint", fakeCognitoEndpointUrl)
    
    val config = AmplifyConfiguration.fromJson(json)
    Amplify.addPlugin(AWSCognitoAuthPlugin())
    Amplfiy.configure(config, context)
    val yourClass = YouClass(auth = Amplify.Auth)
    

    在第二个示例中留下了一些未指定的细节,但希望它足以为您指明工作方向。

    【讨论】:

    • 谢谢你的回答,我一定会试试的。
    猜你喜欢
    • 2020-11-18
    • 2019-12-25
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 2023-03-22
    • 1970-01-01
    • 2012-02-10
    相关资源
    最近更新 更多