Как лучше всего протестировать функцию в моей модели просмотра? - PullRequest
1 голос
/ 20 июня 2020

Недавно я начал внедрять автоматические тесты и немного сомневаюсь, как тестировать свои функции ViewModel. Мой проект следует некоторым концепциям чистой архитектуры, я использую lib kotlin для mockito (https://github.com/nhaarman/mockito-kotlin), и я хотел бы провести следующий тест: When call makeLoginUser get success then set loginUserLiveData.

I я изучил некоторые концепции и знаю, какие тесты мне следует проводить, но я все еще сомневаюсь, как их проводить, какие объекты нужно имитировать для данного теста, а какие нужно создать. Мне нужен был небольшой пример, чтобы обратиться ко мне.

Вот мой тестовый класс и некоторые классы структуры моего проекта.

TestClass

@RunWith(JUnit4::class)
class MainViewModelTest {

    @get:Rule
    var instantTaskExecutorRule = InstantTaskExecutorRule()

    @Mock
    private lateinit var myRepository: MyRepository

    private lateinit var loginUserUseCase: LoginUserUseCase
    private lateinit var checkUserAuthenticatedUsecase: CheckUserAuthenticatedUsecase
    private lateinit var logoutUserUseCase: LogoutUserUseCase

    private lateinit var mainViewModel: MainViewModel

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
    }

    @Test
    fun `When call makeLoginUser get success then set loginUserLiveData`() {
        // prepare
        myRepository = mock { // should I mock or instantiate? 
            on { execLoginUser(ArgumentMatchers.anyString(), ArgumentMatchers.anyString()) } doReturn Flowable.just(true)
        }
        loginUserUseCase = mock { // should I mock or instantiate?
            on { execute(ArgumentMatchers.anyMap()) } doReturn Flowable.just(true)
        }
        mainViewModel = MainViewModel(loginUserUseCase, checkUserAuthenticatedUsecase, logoutUserUseCase)

        val observer = mock<Observer<ResultState<Boolean>>> { mock }

        // Execute
        mainViewModel.makeLoginUser("test@gmail.com", "123456")

        // Check
        // ?
    }

}

ViewModel

// components 'LoginUserUseCase', 'CheckUserAuthenticatedUsecase' and 'LogoutUserUseCase' injected via koin
class MainViewModel(
    private val loginUserUseCase: LoginUserUseCase,
    private val checkUserAuthenticatedUsecase: CheckUserAuthenticatedUsecase,
    private val logoutUserUsecase: LogoutUserUseCase
): BaseViewModel() {

    val loginUserLiveData = MutableLiveData<ResultState<Boolean>>()
    val userAuthenticatedLiveData = MutableLiveData<ResultState<Boolean>>()
    val logoutUserLiveData = MutableLiveData<ResultState<Boolean>>()

    fun makeLoginUser(email: String, password: String) {
        loginUserLiveData.postValue(ResultState.Loading())
        loginUserUseCase.execute(mapOf(EMAIL to email, PASSWORD to password))
            .subscribe({
                loginUserLiveData.postValue(ResultState.Success(it))
            }, {
                loginUserLiveData.postValue(ResultState.Error(it))
            }).addTo(disposables)
    }
...
}

Класс домена прецедента

// components 'ThreadExecutor' and 'PostExecutionThread' injected via koin
abstract class FlowableUseCase<T, in Params> constructor( 
    private val threadExecutor: ThreadExecutor, 
    private val postExecutionThread: PostExecutionThread) { 

    protected abstract fun buildUseCaseObservable(params: Params? = null): Flowable<T> 

    open fun execute(params: Params? = null): Flowable<T> { 
        return this.buildUseCaseObservable(params) 
                .subscribeOn(Schedulers.from(threadExecutor)) 
                .observeOn(postExecutionThread.scheduler) 
    } 

}

Прецеденты абстракции

// components 'MyRepository', 'ThreadExecutor' and 'PostExecutionThread' injected via koin
// 'MyRepository' abstracts remote and local data repository
class LoginUserUseCase(
    private val myRepository: MyRepository,
    threadExecutor: ThreadExecutor,
    postExecutionThread: PostExecutionThread
): FlowableUseCase<Boolean, Map<String, Any>?>(threadExecutor, postExecutionThread) {

    override fun buildUseCaseObservable(params: Map<String, Any>?) = myRepository
        .execLoginUser(
            params?.get(EMAIL) as String,
            params[PASSWORD] as String
        )
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...