В настоящее время я работаю над проектом Android Studio и сейчас проверяю, переключается ли LoginActivity на MainActivity после правильного входа в систему.
Вот код LoginActivity.kt:
24 class LoginActivity : AppCompatActivity() {
26 override fun onCreate(savedInstanceState: Bundle?) {
27 super.onCreate(savedInstanceState)
29 setContentView(R.layout.activity_login)
31 val username = findViewById<EditText>(R.id.username)
32 val password = findViewById<EditText>(R.id.password)
33 val login = findViewById<Button>(R.id.login)
34 val loading = findViewById<ProgressBar>(R.id.loading)
35 val errortext = findViewById<TextView>(R.id.errortext)
36 val registerbutton = findViewById<Button>(R.id.registerbutton)
37 val loginViewModel : LoginViewModel by viewModel()
39 loginViewModel.loginFormState.observe(this@LoginActivity, Observer {
40 val loginState = it ?: return@Observer
42 // disable login button unless both username / password is valid
43 login.isEnabled = loginState.isDataValid
45 if (loginState.usernameError != null) {
46 username.error = getString(loginState.usernameError)
47 }
48 if (loginState.passwordError != null) {
49 password.error = getString(loginState.passwordError)
50 }
51 })
53 loginViewModel.loginResult.observe(this@LoginActivity, Observer {
54 val loginResult = it ?: return@Observer
55 loading.visibility = View.GONE
56 if (loginResult.error != null) {
57 errortext.visibility = View.VISIBLE
58 errortext.text = loginResult.error.message
59 }
60 if (loginResult.success != null) {
61 val sharedPreferences = this.getSharedPreferences("user", Context.MODE_PRIVATE)
62 val mEditor = sharedPreferences.edit()
63 mEditor.putString("currentUser", loginResult.success.jwtToken)
64 mEditor.apply()
65 val intent = Intent(this, MainActivity::class.java)
66 intent.putExtra("hi", "HI")
67 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
68 startActivity(intent)
69 //Complete and destroy login activity once successful
70 setResult(Activity.RESULT_OK)
71 finish()
72 }
73 })
75 username.afterTextChanged {
76 loginViewModel.loginDataChanged(
77 username.text.toString(),
78 password.text.toString()
79 )
80 }
82 password.apply {
83 afterTextChanged {
84 loginViewModel.loginDataChanged(
85 username.text.toString(),
86 password.text.toString()
87 )
88 }
90 setOnEditorActionListener { _, actionId, _ ->
91 when (actionId) {
92 EditorInfo.IME_ACTION_DONE ->
93 loginViewModel.login(
94 username.text.toString(),
95 password.text.toString()
96 )
97 }
98 false
99 }
101 login.setOnClickListener {
102 loading.visibility = View.VISIBLE
103 loginViewModel.login(username.text.toString(), password.text.toString())
104 }
106 registerbutton.setOnClickListener{
107 val intent = Intent(this.context, RegisterActivity::class.java)
108 intent.putExtra("hi", "HI")
109 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
110 startActivity(intent)
111 finish()
112 }
113 }
114 }
115}
Вот код MainActivity.kt:
18 class MainActivity : AppCompatActivity() {
20 private lateinit var drawerLayout : DrawerLayout
21 private lateinit var username: String
22 @RequiresApi(Build.VERSION_CODES.O)
23 override fun onCreate(savedInstanceState: Bundle?) {
24 super.onCreate(savedInstanceState)
25 val sharedPreferences = this.getSharedPreferences("user", Context.MODE_PRIVATE)
26 if(sharedPreferences.contains("currentUser")) {
27 val key = sharedPreferences.getString("currentUser", "")
28 val expiration = JwtUtils.getExpiracyDate(key ?: "")
29 val mEditor = sharedPreferences.edit()
30 if (expiration.before(Date())) {
31 mEditor.remove("currentUser")
32 mEditor.apply()
33 startLogin()
34 }
35 username = JwtUtils.getUsername(key ?: "")
36 }
37 else{
38 startLogin()
39 }
40 val navController = this.findNavController(R.id.menuFragment)
41 val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
42 drawerLayout = binding.drawerLayout
43 NavigationUI.setupActionBarWithNavController(this, navController, drawerLayout)
44 NavigationUI.setupWithNavController(binding.rulechecklist, navController)
45}
47fun startLogin(){
48 val intent = Intent(this, LoginActivity::class.java)
49 intent.putExtra("hi", "HI")
50 intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
51 startActivity(intent)
52}
54override fun onSupportNavigateUp(): Boolean {
55 val navController = this.findNavController(R.id.fragment_register)
56 return NavigationUI.navigateUp(navController, drawerLayout)
57}
58}
Вот код теста Android Studio, который выдает ошибку:
29 @RunWith(AndroidJUnit4::class)
30 @LargeTest
31 class LoginActivityTest : KoinTest{
37 @Test
38 fun LoginActivity_login_CorrectParameters_SwitchesScreens(){
39 stopKoin()
40 startKoin{modules(fakeUserModule)}
41 val scenario = launchActivity<LoginActivity>()
42 scenario.moveToState(Lifecycle.State.RESUMED)
43 onView(withId(R.id.username)).perform(replaceText("Nedl"))
44 onView(withId(R.id.password)).perform(replaceText("Globoesporte"))
45 onView(withId(R.id.login)).perform(click())
46 assertThat(Activity.RESULT_OK, `is`(scenario.result.resultCode))
47}
70}
В настоящее время когда я запускаю тест, это ошибка консоли:
java.lang.IllegalArgumentException: ID does not reference a View inside this Activity
at android.app.Activity.requireViewById(Activity.java:2678)
at androidx.core.app.ActivityCompat.requireViewById(ActivityCompat.java:363)
at androidx.navigation.Navigation.findNavController(Navigation.java:58)
at androidx.navigation.ActivityKt.findNavController(Activity.kt:30)
at com.example.starsign.MainActivity.onCreate(MainActivity.kt:40)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at androidx.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:711)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at androidx.test.espresso.base.Interrogator.loopAndInterrogate(Interrogator.java:148)
at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:525)
at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:484)
at androidx.test.espresso.base.UiControllerImpl.injectMotionEvent(UiControllerImpl.java:236)
at androidx.test.espresso.action.MotionEvents.sendUp(MotionEvents.java:162)
at androidx.test.espresso.action.MotionEvents.sendUp(MotionEvents.java:139)
at androidx.test.espresso.action.Tap.sendSingleTap(Tap.java:170)
at androidx.test.espresso.action.Tap.access$100(Tap.java:31)
at androidx.test.espresso.action.Tap$1.sendTap(Tap.java:47)
at androidx.test.espresso.action.GeneralClickAction.perform(GeneralClickAction.java:137)
at androidx.test.espresso.ViewInteraction$SingleExecutionViewAction.perform(ViewInteraction.java:366)
at androidx.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:255)
at androidx.test.espresso.ViewInteraction.access$100(ViewInteraction.java:65)
at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:158)
at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:155)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Шестая строка сообщения об ошибке указывает, что ошибка связана с тем, что NavController не вводится должным образом в MainActivity. Однако, поскольку тестирование выполняется в LoginActivity, а MainActivity запускается только при нажатии кнопки входа в систему, возникает вопрос, как я могу ввести фиктивный NavController в MainActivity в момент вызова MainActivity. Кто-нибудь может мне помочь?