Arello-Mobile / Moxy

Moxy is MVP library for Android
https://github.com/Arello-Mobile/Moxy/wiki
MIT License
1.61k stars 207 forks source link

What is the right way to test View and Presenter? #213

Closed fylmr closed 5 years ago

fylmr commented 6 years ago

I recently started to get more in deep into popular Android libraries, but I struggle with testing them.

So in my project, among others, I have Moxy and Dagger for MVP and DI, and Mockito, PowerMock and Robolectric for testing. After spending almost all day trying to get two simple test files work, I finally got the working solution. But I feel like it is full of hacks and lacks abstraction: I explicitly used Kotlin open to make my tested classes not final, and my tests fail when I change anything in classes fields and setup() methods.

Is there anything I can do to make it better?

For example, in my LoginActivity test I'm using real class like LoginPresenter, test implementation of FirebaseComponent and FirebaseModel, and mocking FirebaseAuth using Mockito.

@RunWith(RobolectricTestRunner::class)
class LoginActivityTest {

    private var testComponent = TestComponent()
    private lateinit var model: FirebaseModel
    private lateinit var activity: LoginActivity

    @Before
    fun setup() {
        App.firebaseComponent = testComponent

        val auth = Mockito.mock(FirebaseAuth::class.java)
        model = FirebaseModelMock(auth)

        activity = Robolectric.setupActivity(LoginActivity::class.java)
        activity.loginPresenter = LoginPresenter()
        activity.loginPresenter.firebaseModel = model
    }
...
}

Same thing applies to my LoginPresenter test. Here I'm mocking the View and ViewState with Mockito as I've seen in one of Moxy sample projects, creating test Component implementation, and also mocking FirebaseModel with PowerMock.

@RunWith(PowerMockRunner::class)
@PrepareForTest(FirebaseModel::class)
class LoginPresenterTest {

    @Mock
    private
    lateinit var loginView: LoginView
    @Mock
    private
    lateinit var loginViewState: `LoginView$$State`

    private var testComponent = TestComponent()
    private val model: FirebaseModel = PowerMockito.mock(FirebaseModel::class.java)

    private lateinit var presenter: LoginPresenter

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)

        App.firebaseComponent = testComponent

        presenter = LoginPresenter()
        with(presenter) {
            attachView(loginView)
            setViewState(loginViewState)
            firebaseModel = model
        }
    }
...
}

Here is a link to the gist with full files.

senneco commented 5 years ago

Hi,

Is it still actual issue?)