Android协程MVP junit测试代码失败
Android Coroutine MVP junit test code failed
我正在使用 Kotlin(协程)开发玩具 Android 应用程序。
我对Rx比Coroutine更熟悉
感觉Coroutine比Rx难
无论如何,这是我的演示者代码:
class NowPlayingPresenter(
private val view: NowPlayingContract.View,
private val getMovies: GetNowPlayingMovies,
private val uiContext: CoroutineContext = Dispatchers.Main,
ioContext: CoroutineContext = Dispatchers.IO
) : NowPlayingContract.Presenter, CoroutineScope, AnkoLogger {
override val coroutineContext: CoroutineContext = Job() + ioContext
override fun unsubscribe() {
coroutineContext.cancel()
}
override fun getMoviesNowPlaying() {
view.showProgressBar(View.VISIBLE)
view.hideError()
launch {
try {
val movies = getMovies.get()
// 'movies' is always null!!! I don't know why...
withContext(uiContext) {
view.showProgressBar(View.GONE)
if (movies.isNullOrEmpty()) {
view.onError(R.string.err_movies_not_exists)
} else {
view.onMoviesLoaded(movies)
}
}
} catch (t: Throwable) {
view.showProgressBar(View.GONE)
view.onError(R.string.err_get_movies_failed)
error("[Y.M.] getMoviesNowPlaying - failed: ${t.message}", t)
}
}
}
}
这是我的 GetNowPlayingMovies 代码,它只是界面:
interface GetNowPlayingMovies {
suspend fun get(): List<SimpleMovie>
}
下面是我的 JUnit 测试代码:
class MyDataPresenterTest {
@Mock
private lateinit var mockView: NowPlayingContract.View
@Mock
private lateinit var getMovies: GetNowPlayingMovies
private lateinit var presenter: NowPlayingPresenter
private lateinit var inOrder: InOrder
private val mockMovie1 = SimpleMovie("posterpath1", false, "2019-03-01", 10, "hello world1", 10f)
private val mockMovie2 = SimpleMovie("posterpath2", true, "2019-03-02", 20, "hello world2", 9f)
private val mockMovie3 = SimpleMovie("posterpath3", false, "2019-03-03", 30, "hello world3", 8f)
private val mockMovie4 = SimpleMovie("posterpath4", false, "2019-03-04", 40, "hello world4", 7f)
private val mockMovie5 = SimpleMovie("posterpath5", false, "2019-03-05", 50, "hello world5", 6f)
private val mockMovies: List<SimpleMovie> = listOf(
mockMovie1,
mockMovie2,
mockMovie3,
mockMovie4,
mockMovie5
)
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
inOrder = Mockito.inOrder(mockView)
presenter = NowPlayingPresenter(mockView, getMovies, Dispatchers.Unconfined, Dispatchers.Unconfined)
}
@Test
fun getMoviesNowPlayingTest() = runBlocking {
`when`(getMovies.get()).thenReturn(mockMovies)
presenter.getMoviesNowPlaying()
inOrder.verify(mockView).showProgressBar(View.VISIBLE)
inOrder.verify(mockView).hideError()
inOrder.verify(mockView).showProgressBar(View.GONE)
inOrder.verify(mockView).onMoviesLoaded(mockMovies)
}
}
有人帮帮我吗?
这是我的完整代码:
https://github.com/yoonhok524/Android-Sandbox/tree/master/kotlin-coroutine
我尝试在这个项目中应用'Clean architecture',所以代码不太好读...也许...
在我的案例和约定中....
- 实施'CoroutineScope'并覆盖coroutineContext
- coroutineContext = Job() + Dispatchers
(需要 job.cancel() 因为取消了 CoroutineScope 和子项)
- 使用 launch 和 withContext(...)
launch {
val data = withContext(ioContext) {
repository.get(id)
}
withContext(uiContext) {
view?.onDataLoaded(data)
}
}
您正在使用 Mockito 1.x。如果您为挂起功能制作模拟,请使用最新的 Mockito。
我正在使用 Kotlin(协程)开发玩具 Android 应用程序。
我对Rx比Coroutine更熟悉
感觉Coroutine比Rx难
无论如何,这是我的演示者代码:
class NowPlayingPresenter(
private val view: NowPlayingContract.View,
private val getMovies: GetNowPlayingMovies,
private val uiContext: CoroutineContext = Dispatchers.Main,
ioContext: CoroutineContext = Dispatchers.IO
) : NowPlayingContract.Presenter, CoroutineScope, AnkoLogger {
override val coroutineContext: CoroutineContext = Job() + ioContext
override fun unsubscribe() {
coroutineContext.cancel()
}
override fun getMoviesNowPlaying() {
view.showProgressBar(View.VISIBLE)
view.hideError()
launch {
try {
val movies = getMovies.get()
// 'movies' is always null!!! I don't know why...
withContext(uiContext) {
view.showProgressBar(View.GONE)
if (movies.isNullOrEmpty()) {
view.onError(R.string.err_movies_not_exists)
} else {
view.onMoviesLoaded(movies)
}
}
} catch (t: Throwable) {
view.showProgressBar(View.GONE)
view.onError(R.string.err_get_movies_failed)
error("[Y.M.] getMoviesNowPlaying - failed: ${t.message}", t)
}
}
}
}
这是我的 GetNowPlayingMovies 代码,它只是界面:
interface GetNowPlayingMovies {
suspend fun get(): List<SimpleMovie>
}
下面是我的 JUnit 测试代码:
class MyDataPresenterTest {
@Mock
private lateinit var mockView: NowPlayingContract.View
@Mock
private lateinit var getMovies: GetNowPlayingMovies
private lateinit var presenter: NowPlayingPresenter
private lateinit var inOrder: InOrder
private val mockMovie1 = SimpleMovie("posterpath1", false, "2019-03-01", 10, "hello world1", 10f)
private val mockMovie2 = SimpleMovie("posterpath2", true, "2019-03-02", 20, "hello world2", 9f)
private val mockMovie3 = SimpleMovie("posterpath3", false, "2019-03-03", 30, "hello world3", 8f)
private val mockMovie4 = SimpleMovie("posterpath4", false, "2019-03-04", 40, "hello world4", 7f)
private val mockMovie5 = SimpleMovie("posterpath5", false, "2019-03-05", 50, "hello world5", 6f)
private val mockMovies: List<SimpleMovie> = listOf(
mockMovie1,
mockMovie2,
mockMovie3,
mockMovie4,
mockMovie5
)
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
inOrder = Mockito.inOrder(mockView)
presenter = NowPlayingPresenter(mockView, getMovies, Dispatchers.Unconfined, Dispatchers.Unconfined)
}
@Test
fun getMoviesNowPlayingTest() = runBlocking {
`when`(getMovies.get()).thenReturn(mockMovies)
presenter.getMoviesNowPlaying()
inOrder.verify(mockView).showProgressBar(View.VISIBLE)
inOrder.verify(mockView).hideError()
inOrder.verify(mockView).showProgressBar(View.GONE)
inOrder.verify(mockView).onMoviesLoaded(mockMovies)
}
}
有人帮帮我吗?
这是我的完整代码: https://github.com/yoonhok524/Android-Sandbox/tree/master/kotlin-coroutine
我尝试在这个项目中应用'Clean architecture',所以代码不太好读...也许...
在我的案例和约定中....
- 实施'CoroutineScope'并覆盖coroutineContext
- coroutineContext = Job() + Dispatchers (需要 job.cancel() 因为取消了 CoroutineScope 和子项)
- 使用 launch 和 withContext(...)
launch {
val data = withContext(ioContext) {
repository.get(id)
}
withContext(uiContext) {
view?.onDataLoaded(data)
}
}
您正在使用 Mockito 1.x。如果您为挂起功能制作模拟,请使用最新的 Mockito。