Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3d2c588

Browse files
Update README.md
1 parent 5712549 commit 3d2c588

File tree

1 file changed

+168
-1
lines changed

1 file changed

+168
-1
lines changed

‎README.md‎

Lines changed: 168 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
# RxJava-Style-LiveData-TestObserver
1+
# RxJavaStyleLiveData and Flow TestObserver
22
TestObserver class for LiveData to test multiple values like ViewState such as loading, and result states or multiple post and setValues
33

4+
## LiveData
45

56
### Implementation
67

@@ -102,3 +103,169 @@ fun test() {
102103
}
103104
104105
```
106+
107+
## Flow
108+
109+
### Implementation
110+
111+
```
112+
113+
class FlowTestObserver<T>(
114+
coroutineScope: CoroutineScope,
115+
private val flow: Flow<T>
116+
) {
117+
private val testValues = mutableListOf<T>()
118+
private var error: Throwable? = null
119+
120+
// private val job: Job = coroutineScope.launch {
121+
// flow
122+
// .catch { throwable ->
123+
// error = throwable
124+
// }
125+
// .collect {
126+
// testValues.add(it)
127+
// }
128+
// }
129+
130+
private val job: Job = flow
131+
.catch { throwable ->
132+
error = throwable
133+
}
134+
.onEach { testValues.add(it) }
135+
.launchIn(scope = coroutineScope)
136+
137+
138+
fun assertNoValues(): FlowTestObserver<T> {
139+
if (testValues.isNotEmpty()) throw AssertionError(
140+
"Assertion error! Actual size ${testValues.size}"
141+
)
142+
return this
143+
}
144+
145+
fun assertValueCount(count: Int): FlowTestObserver<T> {
146+
if (count < 0) throw AssertionError(
147+
"Assertion error! Value count cannot be smaller than zero"
148+
)
149+
if (count != testValues.size) throw AssertionError(
150+
"Assertion error! Expected $count while actual ${testValues.size}"
151+
)
152+
return this
153+
}
154+
155+
fun assertValues(vararg values: T): FlowTestObserver<T> {
156+
if (!testValues.containsAll(values.asList()))
157+
throw AssertionError("Assertion error! At least one value does not match")
158+
return this
159+
}
160+
161+
// fun assertValues(predicate: List<T>.() -> Boolean): FlowTestObserver<T> {
162+
// if (!testValues.predicate())
163+
// throw AssertionError("Assertion error! At least one value does not match")
164+
// return this
165+
// }
166+
//
167+
// fun values(predicate: List<T>.() -> Unit): FlowTestObserver<T> {
168+
// testValues.predicate()
169+
// return this
170+
// }
171+
172+
fun assertValues(predicate: (List<T>) -> Boolean): FlowTestObserver<T> {
173+
if (!predicate(testValues))
174+
throw AssertionError("Assertion error! At least one value does not match")
175+
return this
176+
}
177+
178+
fun assertError(throwable: Throwable): FlowTestObserver<T> {
179+
180+
val errorNotNull = exceptionNotNull()
181+
182+
if (!(errorNotNull::class.java == throwable::class.java &&
183+
errorNotNull.message == throwable.message)
184+
)
185+
throw AssertionError("Assertion Error! throwable: $throwable does not match $errorNotNull")
186+
187+
return this
188+
}
189+
190+
fun assertError(errorClass: Class<Throwable>): FlowTestObserver<T> {
191+
192+
val errorNotNull = exceptionNotNull()
193+
194+
if (errorNotNull::class.java != errorClass)
195+
throw AssertionError("Assertion Error! errorClass $errorClass does not match ${errorNotNull::class.java}")
196+
197+
return this
198+
}
199+
200+
fun assertError(predicate: (Throwable) -> Boolean): FlowTestObserver<T> {
201+
202+
val errorNotNull = exceptionNotNull()
203+
204+
if (!predicate(errorNotNull))
205+
throw AssertionError("Assertion Error! Exception for $errorNotNull")
206+
207+
return this
208+
}
209+
210+
fun assertNull(): FlowTestObserver<T> {
211+
212+
testValues.forEach {
213+
if (it != null) throw AssertionError("Assertion Error! There are more than one item that is not nuşş")
214+
215+
}
216+
217+
return this
218+
}
219+
220+
fun values(predicate: (List<T>) -> Unit): FlowTestObserver<T> {
221+
predicate(testValues)
222+
return this
223+
}
224+
225+
fun values(): List<T> {
226+
return testValues
227+
}
228+
229+
private fun exceptionNotNull(): Throwable {
230+
231+
if (error == null)
232+
throw AssertionError("There is no exception")
233+
234+
return error!!
235+
}
236+
237+
fun dispose() {
238+
job.cancel()
239+
}
240+
}
241+
242+
fun <T> Flow<T>.test(scope: CoroutineScope): FlowTestObserver<T> {
243+
return FlowTestObserver(scope, this)
244+
}
245+
246+
```
247+
248+
## Usage
249+
```
250+
postRemoteRepository.getPostFlow()
251+
.test(testCoroutineScope)
252+
// .assertError(Exception("Network Exception"))
253+
.assertError {
254+
it.message == "Network Exception"
255+
}
256+
.dispose()
257+
258+
259+
testCoroutineScope.runBlockingTest {
260+
261+
// GIVEN
262+
every { postDBRepository.getPostListFlow() } returns flow { emit(listOf()) }
263+
264+
// WHEN
265+
val testObserver = postDBRepository.getPostListFlow().test(this)
266+
267+
// THEN
268+
val actual = testObserver.values()[0]
269+
Truth.assertThat(actual.size).isEqualTo(0)
270+
testObserver.dispose()
271+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /