【发布时间】:2019-06-05 04:58:57
【问题描述】:
我正在使用 Kotlin(协程)开发一个玩具 Android 应用。
比起 Coroutine,我更熟悉 Rx。
我觉得 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
我尝试在这个项目中应用“清洁架构”,所以代码不容易阅读......也许......
【问题讨论】:
-
如果您发布创建
mockData目标代码会很有用。 -
可以分享一下测试失败的消息吗?
-
r2rek,我已经在 Presenter 代码中写了错误消息作为注释。
-
Ircover,它只是简单的数据类列表,当我在测试代码中检查它时,它不为空。
标签: android kotlin junit coroutine clean-architecture