Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
135 views
in Technique[技术] by (71.8m points)

How to create unit test when u'r view model & repository return live data for Android

I already create some unit test for my view model. but when I println() the result it always return State Loading.. I have tried to read some article and cek in other source code but I'm still not found the answer.

Here is my code from ViewModel :

class PredefineViewModel() : ViewModel() {

private var predefineRepository: PredefineRepository? = PredefineRepository()

private val _predefined = MutableLiveData<String>()

val predefined: LiveData<Resource<Payload<Predefine>>> =
        Transformations.switchMap(_predefined) {
            predefineRepository?.predefine()
        }

fun predefined() {
        _predefined.value = "predefined".random().toString()
    }

}

Here is my Repository

class PredefineRepository()  {

private val api: PredefineApi? = PredefineApi.init()

fun predefine(): BaseMutableLiveData<Predefine> {
        val predefine: BaseMutableLiveData<Predefine> = BaseMutableLiveData()

        api?.let { api ->
            predefine.isLoading()

            api.predefined().observe()?.subscribe({ response ->
                response?.let { resource ->
                    predefine.isSuccess(resource)
                }
            }, { error ->
                predefine.isError(error)
            })
        }


        return predefine
    }

}

Here is my Resources State :

data class Resource<T>(var status: Status? = null, var meta: Meta? = null, var payload: T? =null) {
    companion object {
        fun <T> success(data: T?, meta: Meta): Resource<T> {
            return Resource(Status.SUCCESS, meta, data)
        }

        fun <T> error(data: T?, meta: Meta): Resource<T> {
            return Resource(Status.ERROR, meta, data)
        }

        fun <T> loading(data: T?, meta: Meta): Resource<T> {
            return Resource(Status.LOADING, null, null)
        }
    }
}

UPDATE TEST CLASS And, This is sample I try to print and check value from my live data view model :

class PredefineViewModelTest {

    @get:Rule
    val taskExecutorRule = InstantTaskExecutorRule()

    private lateinit var viewModel: PredefineViewModel
    private lateinit var repository: PredefineRepository
    private lateinit var api: Api

    @Before
    fun setUp() {
        api = Networks().bridge().create(Api::class.java)
        repository = PredefineRepository()
        viewModel = PredefineViewModel()
    }

    @Test
    fun test_predefined(){
        val data = BaseMutableLiveData<Predefine>()

        val result = api.predefined()
        result.test().await().assertComplete()
        result.subscribe {
            data.isSuccess(it)
        }

        `when`(repository.predefine()).thenReturn(data)

        viewModel.predefined()
        viewModel.predefined.observeForever {
            println("value: $it")
            println("data: ${data.value}")
        }
    }

}

UPDATE LOG Results Why the result from my predefined always:

value: Resource(status=LOADING, meta=null, payload=null, errorData=[])

data: Resource(status=SUCCESS, meta=Meta(code=200, message=success, error=null), payload= Data(code=200, message=success, errorDara =[])

Thank You..

question from:https://stackoverflow.com/questions/65934875/how-to-create-unit-test-when-ur-view-model-repository-return-live-data-for-an

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You would require to mock your API response. The unit test won't run your API actually you have to mock that. Please have a look at the attached snippet, It will give you a basic idea of how you can achieve that.

ViewModel:

class MainViewModel(val repository: Repository) : ViewModel() {

    fun fetchData(): LiveData<Boolean> {
        return Transformations.map(repository.getData()) {
            if (it.status == 200) {
                true
            } else {
                false
            }
        }
    }
}

Repo:

open class Repository {

    open fun getData() : LiveData<MainModel> {
        return MutableLiveData(MainModel(10, 200))
    }
}

Test Class:

@RunWith(MockitoJUnitRunner::class)
 class MainViewModelTest {

    lateinit var mainModel: MainViewModel

    @Rule
    @JvmField
    var rule: TestRule = InstantTaskExecutorRule()

    @Mock
    lateinit var repo: Repository

    init {
        MockitoAnnotations.initMocks(this)
    }

    @Before
    fun setup() {
        mainModel = MainViewModel(repo)
    }

    @Test
    fun fetchData_success() {
             val mainModelData = MainModel(10, 200)
        `when`(repo.getData()).thenReturn(MutableLiveData(mainModelData))


        mainModel.fetchData().observeForever {
            Assert.assertTrue(it)
        }
    }

    @Test
    fun fetchData_failure() {
        val mainModelData = MainModel(10, 404)
        `when`(repo.getData()).thenReturn(MutableLiveData(mainModelData))

        mainModel.fetchData().observeForever {
            Assert.assertFalse(it)
        }
    }

}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...