[英]Mocking AWS Amplify Auth APIs for Android
My Android application uses AWS Cognito and Amplify Auth SDK for authentication and I'm trying to write JUnit test cases for login/signup flows.我的 Android 应用程序使用AWS Cognito 和 Amplify Auth SDK进行身份验证,我正在尝试为登录/注册流程编写 JUnit 测试用例。 I'm using Mockito framework to mock the classes.
我正在使用 Mockito 框架来模拟这些类。
I started with login, my login model looks like this我从登录开始,我的登录 model 看起来像这样
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
}
}
And my viewmodel calls it this way我的视图模型这样称呼它
class LoginViewModel : ViewModel() {
val loginService = LoginService(Amplify.Auth)
fun login(username: String, password: String): MutableLiveData<Login> {
return loginService.login(username, password)
}
}
And my test case looks like this我的测试用例看起来像这样
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!!)
}
}
Please help me validate this approach, I'm trying to find out a way to trigger AuthSignInResult
and AuthException
of Auth.signIn()
method so that I would assert if signin is successful or there is an error.请帮助我验证这种方法,我正在尝试找到一种方法来触发 Auth.signIn
Auth.signIn()
方法的AuthSignInResult
和AuthException
,以便我断言登录是否成功或有错误。
I'm very new to AWS Amplify and Cognito environment, A suggestion/reference to do this in correct way would be highly appreciated.我对 AWS Amplify 和 Cognito 环境非常陌生,非常感谢以正确方式执行此操作的建议/参考。 Thanks in advance.
提前致谢。
There are a couple ways you can encourage testability with Amplify Android.您可以通过多种方式使用 Amplify Android 来鼓励可测试性。 Of the two below, I would definitely start with the first approach.
在下面的两个中,我肯定会从第一种方法开始。
This is a "unit test" level approach.这是一种“单元测试”级别的方法。
Amplify.Auth
implements the AuthCategoryBehavior
interface. Amplify.Auth
实现了AuthCategoryBehavior
接口。 So, if you change all of your code to use that interface, you can just mock it.因此,如果您更改所有代码以使用该接口,则可以模拟它。
Say you have some class which uses Auth as a dependency:假设您有一些 class 使用 Auth 作为依赖项:
class YourClass(private val auth: AuthCategoryBehavior = Amplify.Auth) {
...
}
Now, in your production code, you'd have your Dependency Injection code do something like this:现在,在您的生产代码中,您将让您的依赖注入代码执行以下操作:
addPlugin(AWSCognitoAuthPlugin())
, Ampify.configure(...)
, etc.)addPlugin(AWSCognitoAuthPlugin())
、 Ampify.configure(...)
等)YourClass
, built from YourClass(auth = Amplify.Auth)
YourClass
,由YourClass(auth = Amplify.Auth)
However in your test code , you can build an instance of YourClass
using a mock of the Amplify Auth stuff:但是,在您的测试代码中,您可以使用 Amplify Auth 的模拟来构建
YourClass
的实例:
val mockAuth = mock(AuthCategoryBehavior::class.java)
val yourClass = YourClass(mockAuth)
With that, you can specify how it should behave under test conditions:有了它,您可以指定它在测试条件下的行为方式:
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())
MockWebServer
MockWebServer
This is more of a "component" or "integration" level approach.这更像是一种“组件”或“集成”级别的方法。 Here, we'll use a
MockWebServer
instance to return canned responses from a fake Cognito server.在这里,我们将使用
MockWebServer
实例从假的 Cognito 服务器返回预设响应。
In this flow, you're using all of the real Amplify library code, in both production and in test.在此流程中,您将在生产和测试中使用所有真正的 Amplify 库代码。 Just making believe you can control Cognito's responses to the client.
只是让人相信你可以控制 Cognito 对客户的回应。
To do this, you should view the actual HTTP responses in your Android Studio's Network Monitor tab.为此,您应该在 Android Studio 的网络监视器选项卡中查看实际的 HTTP 响应。 Then, arrange that content into the test code below.
然后,将该内容安排到下面的测试代码中。
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)
Have left a few details unspecified in this second example, but hopefully it's enough to set you in a working direction.在第二个示例中留下了一些未指定的细节,但希望它足以让您确定工作方向。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.