Skip to content

Commit 2e29705

Browse files
authored
Merge pull request #9 from bufferapp/task/fix-data-store-data-source
[FIXES] Only save bufferoos when fetched from remote data source
2 parents 57de245 + 3dfc9f3 commit 2e29705

File tree

5 files changed

+187
-10
lines changed

5 files changed

+187
-10
lines changed

data/src/main/java/org/buffer/android/boilerplate/data/BufferooDataRepository.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import io.reactivex.Single
55
import org.buffer.android.boilerplate.data.mapper.BufferooMapper
66
import org.buffer.android.boilerplate.data.model.BufferooEntity
77
import org.buffer.android.boilerplate.data.source.BufferooDataStoreFactory
8+
import org.buffer.android.boilerplate.data.source.BufferooRemoteDataStore
89
import org.buffer.android.boilerplate.domain.model.Bufferoo
910
import org.buffer.android.boilerplate.domain.repository.BufferooRepository
1011
import javax.inject.Inject
@@ -28,14 +29,20 @@ class BufferooDataRepository @Inject constructor(private val factory: BufferooDa
2829
}
2930

3031
override fun getBufferoos(): Single<List<Bufferoo>> {
31-
return factory.retrieveDataStore().getBufferoos()
32+
val dataStore = factory.retrieveDataStore()
33+
return dataStore.getBufferoos()
3234
.flatMap {
3335
val bufferoos = mutableListOf<Bufferoo>()
3436
it.map { bufferoos.add(bufferooMapper.mapFromEntity(it)) }
35-
saveBufferoos(bufferoos)
36-
.andThen(Single.just(bufferoos))
37+
Single.just(bufferoos)
38+
}
39+
.flatMap {
40+
if (dataStore is BufferooRemoteDataStore) {
41+
saveBufferoos(it).toSingle { it }
42+
} else {
43+
Single.just(it)
44+
}
3745
}
38-
3946
}
4047

4148
}

data/src/main/java/org/buffer/android/boilerplate/data/mapper/BufferooMapper.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import javax.inject.Inject
99
* Map a [BufferooEntity] to and from a [Bufferoo] instance when data is moving between
1010
* this later and the Domain layer
1111
*/
12-
class BufferooMapper @Inject constructor(): Mapper<BufferooEntity, Bufferoo> {
12+
open class BufferooMapper @Inject constructor(): Mapper<BufferooEntity, Bufferoo> {
1313

1414
/**
1515
* Map a [BufferooEntity] instance to a [Bufferoo] instance

data/src/main/java/org/buffer/android/boilerplate/data/source/BufferooDataStoreFactory.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import javax.inject.Inject
77
/**
88
* Create an instance of a BufferooDataStore
99
*/
10-
class BufferooDataStoreFactory @Inject constructor(
10+
open class BufferooDataStoreFactory @Inject constructor(
1111
private val bufferooCache: BufferooCache,
1212
private val bufferooCacheDataStore: BufferooCacheDataStore,
1313
private val bufferooRemoteDataStore: BufferooRemoteDataStore) {
@@ -16,7 +16,7 @@ class BufferooDataStoreFactory @Inject constructor(
1616
* Returns a DataStore based on whether or not there is content in the cache and the cache
1717
* has not expired
1818
*/
19-
fun retrieveDataStore(): BufferooDataStore {
19+
open fun retrieveDataStore(): BufferooDataStore {
2020
if (bufferooCache.isCached() && !bufferooCache.isExpired()) {
2121
return retrieveCacheDataStore()
2222
}
@@ -26,14 +26,14 @@ class BufferooDataStoreFactory @Inject constructor(
2626
/**
2727
* Return an instance of the Remote Data Store
2828
*/
29-
fun retrieveCacheDataStore(): BufferooDataStore {
29+
open fun retrieveCacheDataStore(): BufferooDataStore {
3030
return bufferooCacheDataStore
3131
}
3232

3333
/**
3434
* Return an instance of the Cache Data Store
3535
*/
36-
fun retrieveRemoteDataStore(): BufferooDataStore {
36+
open fun retrieveRemoteDataStore(): BufferooDataStore {
3737
return bufferooRemoteDataStore
3838
}
3939

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package org.buffer.android.boilerplate.data
2+
3+
import com.nhaarman.mockito_kotlin.*
4+
import io.reactivex.Completable
5+
import io.reactivex.Single
6+
import org.buffer.android.boilerplate.data.mapper.BufferooMapper
7+
import org.buffer.android.boilerplate.data.model.BufferooEntity
8+
import org.buffer.android.boilerplate.data.repository.BufferooDataStore
9+
import org.buffer.android.boilerplate.data.source.BufferooCacheDataStore
10+
import org.buffer.android.boilerplate.data.source.BufferooDataStoreFactory
11+
import org.buffer.android.boilerplate.data.source.BufferooRemoteDataStore
12+
import org.buffer.android.boilerplate.data.test.factory.BufferooFactory
13+
import org.buffer.android.boilerplate.domain.model.Bufferoo
14+
import org.junit.Before
15+
import org.junit.Test
16+
import org.junit.runner.RunWith
17+
import org.junit.runners.JUnit4
18+
19+
@RunWith(JUnit4::class)
20+
class BufferooDataRepositoryTest {
21+
22+
private lateinit var bufferooDataRepository: BufferooDataRepository
23+
24+
private lateinit var bufferooDataStoreFactory: BufferooDataStoreFactory
25+
private lateinit var bufferooMapper: BufferooMapper
26+
private lateinit var bufferooCacheDataStore: BufferooCacheDataStore
27+
private lateinit var bufferooRemoteDataStore: BufferooRemoteDataStore
28+
29+
@Before
30+
fun setUp() {
31+
bufferooDataStoreFactory = mock()
32+
bufferooMapper = mock()
33+
bufferooCacheDataStore = mock()
34+
bufferooRemoteDataStore = mock()
35+
bufferooDataRepository = BufferooDataRepository(bufferooDataStoreFactory, bufferooMapper)
36+
stubBufferooDataStoreFactoryRetrieveCacheDataStore()
37+
stubBufferooDataStoreFactoryRetrieveRemoteDataStore()
38+
}
39+
40+
//<editor-fold desc="Clear Bufferoos">
41+
@Test
42+
fun clearBufferoosCompletes() {
43+
stubBufferooCacheClearBufferoos(Completable.complete())
44+
val testObserver = bufferooDataRepository.clearBufferoos().test()
45+
testObserver.assertComplete()
46+
}
47+
48+
@Test
49+
fun clearBufferoosCallsCacheDataStore() {
50+
stubBufferooCacheClearBufferoos(Completable.complete())
51+
bufferooDataRepository.clearBufferoos().test()
52+
verify(bufferooCacheDataStore).clearBufferoos()
53+
}
54+
55+
@Test
56+
fun clearBufferoosNeverCallsRemoteDataStore() {
57+
stubBufferooCacheClearBufferoos(Completable.complete())
58+
bufferooDataRepository.clearBufferoos().test()
59+
verify(bufferooRemoteDataStore, never()).clearBufferoos()
60+
}
61+
//</editor-fold>
62+
63+
//<editor-fold desc="Save Bufferoos">
64+
@Test
65+
fun saveBufferoosCompletes() {
66+
stubBufferooCacheSaveBufferoos(Completable.complete())
67+
val testObserver = bufferooDataRepository.saveBufferoos(
68+
BufferooFactory.makeBufferooList(2)).test()
69+
testObserver.assertComplete()
70+
}
71+
72+
@Test
73+
fun saveBufferoosCallsCacheDataStore() {
74+
stubBufferooCacheSaveBufferoos(Completable.complete())
75+
bufferooDataRepository.saveBufferoos(BufferooFactory.makeBufferooList(2)).test()
76+
verify(bufferooCacheDataStore).saveBufferoos(any())
77+
}
78+
79+
@Test
80+
fun saveBufferoosNeverCallsRemoteDataStore() {
81+
stubBufferooCacheSaveBufferoos(Completable.complete())
82+
bufferooDataRepository.saveBufferoos(BufferooFactory.makeBufferooList(2)).test()
83+
verify(bufferooRemoteDataStore, never()).saveBufferoos(any())
84+
}
85+
//</editor-fold>
86+
87+
//<editor-fold desc="Get Bufferoos">
88+
@Test
89+
fun getBufferoosCompletes() {
90+
stubBufferooDataStoreFactoryRetrieveDataStore(bufferooCacheDataStore)
91+
stubBufferooCacheDataStoreGetBufferoos(Single.just(
92+
BufferooFactory.makeBufferooEntityList(2)))
93+
val testObserver = bufferooDataRepository.getBufferoos().test()
94+
testObserver.assertComplete()
95+
}
96+
97+
@Test
98+
fun getBufferoosReturnsData() {
99+
stubBufferooDataStoreFactoryRetrieveDataStore(bufferooCacheDataStore)
100+
val bufferoos = BufferooFactory.makeBufferooList(2)
101+
val bufferooEntities = BufferooFactory.makeBufferooEntityList(2)
102+
bufferoos.forEachIndexed { index, bufferoo ->
103+
stubBufferooMapperMapFromEntity(bufferooEntities[index], bufferoo) }
104+
stubBufferooCacheDataStoreGetBufferoos(Single.just(bufferooEntities))
105+
106+
val testObserver = bufferooDataRepository.getBufferoos().test()
107+
testObserver.assertValue(bufferoos)
108+
}
109+
110+
@Test
111+
fun getBufferoosSavesBufferoosWhenFromCacheDataStore() {
112+
stubBufferooDataStoreFactoryRetrieveDataStore(bufferooCacheDataStore)
113+
stubBufferooCacheSaveBufferoos(Completable.complete())
114+
bufferooDataRepository.saveBufferoos(BufferooFactory.makeBufferooList(2)).test()
115+
verify(bufferooCacheDataStore).saveBufferoos(any())
116+
}
117+
118+
@Test
119+
fun getBufferoosNeverSavesBufferoosWhenFromRemoteDataStore() {
120+
stubBufferooDataStoreFactoryRetrieveDataStore(bufferooRemoteDataStore)
121+
stubBufferooCacheSaveBufferoos(Completable.complete())
122+
bufferooDataRepository.saveBufferoos(BufferooFactory.makeBufferooList(2)).test()
123+
verify(bufferooRemoteDataStore, never()).saveBufferoos(any())
124+
}
125+
//</editor-fold>
126+
127+
//<editor-fold desc="Stub helper methods">
128+
private fun stubBufferooCacheSaveBufferoos(completable: Completable) {
129+
whenever(bufferooCacheDataStore.saveBufferoos(any()))
130+
.thenReturn(completable)
131+
}
132+
133+
private fun stubBufferooCacheDataStoreGetBufferoos(single: Single<List<BufferooEntity>>) {
134+
whenever(bufferooCacheDataStore.getBufferoos())
135+
.thenReturn(single)
136+
}
137+
138+
private fun stubBufferooRemoteDataStoreGetBufferoos(single: Single<List<BufferooEntity>>) {
139+
whenever(bufferooRemoteDataStore.getBufferoos())
140+
.thenReturn(single)
141+
}
142+
143+
private fun stubBufferooCacheClearBufferoos(completable: Completable) {
144+
whenever(bufferooCacheDataStore.clearBufferoos())
145+
.thenReturn(completable)
146+
}
147+
148+
private fun stubBufferooDataStoreFactoryRetrieveCacheDataStore() {
149+
whenever(bufferooDataStoreFactory.retrieveCacheDataStore())
150+
.thenReturn(bufferooCacheDataStore)
151+
}
152+
153+
private fun stubBufferooDataStoreFactoryRetrieveRemoteDataStore() {
154+
whenever(bufferooDataStoreFactory.retrieveRemoteDataStore())
155+
.thenReturn(bufferooCacheDataStore)
156+
}
157+
158+
private fun stubBufferooDataStoreFactoryRetrieveDataStore(dataStore: BufferooDataStore) {
159+
whenever(bufferooDataStoreFactory.retrieveDataStore())
160+
.thenReturn(dataStore)
161+
}
162+
163+
private fun stubBufferooMapperMapFromEntity(bufferooEntity: BufferooEntity,
164+
bufferoo: Bufferoo) {
165+
whenever(bufferooMapper.mapFromEntity(bufferooEntity))
166+
.thenReturn(bufferoo)
167+
}
168+
//</editor-fold>
169+
170+
}

domain/src/main/java/org/buffer/android/boilerplate/domain/model/Bufferoo.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ package org.buffer.android.boilerplate.domain.model
33
/**
44
* Representation for a [Bufferoo] fetched from an external layer data source
55
*/
6-
class Bufferoo(val name: String, val title: String, val avatar: String)
6+
data class Bufferoo(val name: String, val title: String, val avatar: String)

0 commit comments

Comments
 (0)