Repository Unit Tests #50

Merged
AmineB merged 38 commits from davidoskky/ReaderForSelfoss-multiplatform:repository_tests into master 2022-09-30 11:31:55 +00:00
2 changed files with 78 additions and 19 deletions
Showing only changes of commit 920d4ac1ef - Show all commits

View File

@ -37,6 +37,9 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
var badgeStarred = 0
set(value) {field = if (value < 0) { 0 } else { value } }
private var fetchedSources = false
private var fetchedTags = false
AmineB marked this conversation as resolved Outdated

What does this change do ?

What does this change do ?

This does not change the behavior of the function at all.
runBlocking and Dispatchers.Main are basically the same thing.
However, the testing framework for the common code does not support Dispatchers.
This edit serves pretty much just to make the tests work properly.

I'm certain there is some way to make it work keeping the Dispatchers in there, but since these are equivalent I preferred saving some time and just slightly change the function.

This does not change the behavior of the function at all. runBlocking and Dispatchers.Main are basically the same thing. However, the testing framework for the common code does not support Dispatchers. This edit serves pretty much just to make the tests work properly. I'm certain there is some way to make it work keeping the Dispatchers in there, but since these are equivalent I preferred saving some time and just slightly change the function.
init {
// TODO: Dispatchers.IO not available in KMM, an alternative solution should be found
runBlocking {
@ -144,13 +147,17 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
}
suspend fun getTags(): List<SelfossModel.Tag> {
return if (isNetworkAvailable()) {
val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
return if (isNetworkAvailable() && !fetchedTags) {
val apiTags = api.tags()
if (apiTags.success && apiTags.data != null && (appSettingsService.isItemCachingEnabled() || appSettingsService.isUpdateSourcesEnabled())) {
if (apiTags.success && apiTags.data != null && isDatabaseEnabled) {
resetDBTagsWithData(apiTags.data)
if (!appSettingsService.isUpdateSourcesEnabled()) {
fetchedTags = true
}
}
apiTags.data ?: emptyList()
} else if (appSettingsService.isItemCachingEnabled() || appSettingsService.isUpdateSourcesEnabled()) {
} else if (isDatabaseEnabled) {
getDBTags().map { it.toView() }
} else {
emptyList()
@ -172,13 +179,17 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
}
suspend fun getSources(): ArrayList<SelfossModel.Source> {
return if (isNetworkAvailable()) {
val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
return if (isNetworkAvailable() && !fetchedSources) {
val apiSources = api.sources()
if (apiSources.success && apiSources.data != null && (appSettingsService.isItemCachingEnabled() || appSettingsService.isUpdateSourcesEnabled())) {
if (apiSources.success && apiSources.data != null && isDatabaseEnabled) {
resetDBSourcesWithData(apiSources.data)
if (!appSettingsService.isUpdateSourcesEnabled()) {
fetchedSources = true
}
}
apiSources.data ?: ArrayList()
} else if (appSettingsService.isItemCachingEnabled() || appSettingsService.isUpdateSourcesEnabled()) {
} else if (isDatabaseEnabled) {
ArrayList(getDBSources().map { it.toView() })
} else {
ArrayList()

View File

@ -342,12 +342,35 @@ class RepositoryTest() {
testTags = repository.getTags()
}
coVerify(exactly = 1) { api.tags() }
assertNotSame(tags, testTags)
assertContentEquals(tagsDB.map { it.toView() }, testTags)
coVerify(exactly = 1) { api.tags() }
verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() }
}
@Test
fun `Get tags with items caching disabled`() {
AmineB marked this conversation as resolved Outdated

Why is this called twice ?

Why is this called twice ?

To test that api.tags() gets called only once regardless of how many calls are made to the repository.

To test that api.tags() gets called only once regardless of how many calls are made to the repository.
val tags = listOf(SelfossModel.Tag("test", "red", 6),
SelfossModel.Tag("second", "yellow", 0))
val tagsDB = listOf(TAG("test_DB", "red", 6),
TAG("second_DB", "yellow", 0))
coEvery { api.tags() } returns SelfossModel.StatusAndData(success = true, data = tags)
coEvery { db.tagsQueries.tags().executeAsList() } returns tagsDB
every { appSettingsService.isUpdateSourcesEnabled() } returns true
every { appSettingsService.isItemCachingEnabled() } returns false
val repository = Repository(api, appSettingsService, connectivityStatus, db)
var testTags: List<SelfossModel.Tag> = emptyList()
runBlocking {
testTags = repository.getTags()
}
assertSame(tags, testTags)
coVerify(exactly = 1) { api.tags() }
verify(exactly = 0) { db.tagsQueries.tags().executeAsList() }
}
@Test
fun `Get tags with sources update and items caching disabled`() {
val tags = listOf(SelfossModel.Tag("test", "red", 6),
@ -364,11 +387,13 @@ class RepositoryTest() {
var testTags: List<SelfossModel.Tag> = emptyList()
runBlocking {
testTags = repository.getTags()
testTags = repository.getTags()
}
AmineB marked this conversation as resolved Outdated

Tags and sources caching is handled via the update_sources setting.

Also, disabling that setting should clear the DB (this is not the case yet)

So this line should return null, as we won't check for the update_sources setting every time we try to fetch the db data.

Tags and sources caching is handled via the update_sources setting. Also, disabling that setting should clear the DB (this is not the case yet) So this line should return null, as we won't check for the update_sources setting every time we try to fetch the db data.

Returning null isn't possible, so it should be an empty list.

Returning `null` isn't possible, so it should be an empty list.

Why is tags caching handled by update_sources?

Why is tags caching handled by update_sources?

Because it's handled separatly, so users can cache the sources/tags without caching anything else.

Because it's handled separatly, so users can cache the sources/tags without caching anything else.

I don't think sources and tags should be cached if items are not cached; what would be the use of such a function?

I don't think sources and tags should be cached if items are not cached; what would be the use of such a function?

I don't think sources and tags should be cached if items are not cached; what would be the use of such a function?

As mentionnend by you in a previous comment, it is used to limit the ammount of calls to the selfoss instance, by limiting the call to tags/sources routes.

> I don't think sources and tags should be cached if items are not cached; what would be the use of such a function? As mentionnend by you in a previous comment, it is used to limit the ammount of calls to the selfoss instance, by limiting the call to tags/sources routes.
assertSame(tags, testTags)
coVerify(exactly = 1) { api.tags() }
verify(exactly = 0) { db.tagsQueries.tags().executeAsList() }
assertNotSame(tags, testTags)
assertContentEquals(tagsDB.map { it.toView() }, testTags)
verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() }
}
@Test
@ -415,9 +440,9 @@ class RepositoryTest() {
testTags = repository.getTags()
}
assertContentEquals(tagsDB.map { it.toView() }, testTags)
assertSame(emptyList(), testTags)
coVerify(exactly = 0) { api.tags() }
verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() }
verify(exactly = 0) { db.tagsQueries.tags().executeAsList() }
AmineB marked this conversation as resolved Outdated

The same comments about Get tags without connection and items caching disabled should be considered here.

The same comments about `Get tags without connection and items caching disabled` should be considered here.
}
@Test
@ -464,9 +489,9 @@ class RepositoryTest() {
testTags = repository.getTags()
}
assertSame(emptyList(), testTags)
assertContentEquals(tagsDB.map { it.toView() }, testTags)
coVerify(exactly = 0) { api.tags() }
verify(exactly = 0) { db.tagsQueries.tags().executeAsList() }
verify(atLeast = 1) { db.tagsQueries.tags().executeAsList() }
}
@Test
@ -497,6 +522,7 @@ class RepositoryTest() {
SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png"))
every { appSettingsService.isUpdateSourcesEnabled() } returns false
every { appSettingsService.isItemCachingEnabled() } returns true
coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources)
every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB
val repository = Repository(api, appSettingsService, connectivityStatus, db)
@ -507,12 +533,34 @@ class RepositoryTest() {
testSources = repository.getSources()
}
coVerify(exactly = 1) { api.sources() }
assertNotSame(sources, testSources)
assertContentEquals(sourcesDB.map { it.toView() }, testSources)
coVerify(exactly = 1) { api.sources() }
verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() }
}
@Test
fun `get sources with items caching disabled`() {
val sources = arrayListOf(SelfossModel.Source(1, "First source", listOf("Test", "second"),"spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"),
SelfossModel.Source(2, "Second source", listOf("second"),"spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png"))
val sourcesDB = listOf<SOURCE>(SOURCE("1", "First source", "Test,second","spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"),
SOURCE("2", "Second source", "second","spouts\\rss\\fulltextrss", "", "b3aa8a664d08eb15d6ff1db2fa83e0d9.png"))
every { appSettingsService.isUpdateSourcesEnabled() } returns true
every { appSettingsService.isItemCachingEnabled() } returns false
coEvery { api.sources() } returns SelfossModel.StatusAndData(success = true, data = sources)
every { db.sourcesQueries.sources().executeAsList() } returns sourcesDB
val repository = Repository(api, appSettingsService, connectivityStatus, db)
var testSources: List<SelfossModel.Source>? = null
runBlocking {
testSources = repository.getSources()
}
assertSame(sources, testSources)
coVerify(exactly = 1) { api.sources() }
verify(exactly = 0) { db.sourcesQueries }
}
@Test
fun `get sources with sources update and items caching disabled`() {
val sources = arrayListOf(SelfossModel.Source(1, "First source", listOf("Test", "second"),"spouts\\rss\\fulltextrss", "", "d8c92cdb1ef119ea85c4b9205c879ca7.png"),
@ -532,7 +580,7 @@ class RepositoryTest() {
assertSame(sources, testSources)
coVerify(exactly = 1) { api.sources() }
verify(exactly = 0) { db.sourcesQueries.sources().executeAsList() }
verify(atLeast = 1) { db.sourcesQueries }
}
@Test
@ -574,9 +622,9 @@ class RepositoryTest() {
testSources = repository.getSources()
}
assertContentEquals(sourcesDB.map { it.toView() }, testSources)
assertContentEquals(ArrayList(), testSources)
coVerify(exactly = 0) { api.sources() }
verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() }
verify(exactly = 0) { db.sourcesQueries.sources().executeAsList() }
}
@Test
@ -620,9 +668,9 @@ class RepositoryTest() {
testSources = repository.getSources()
}
assertContentEquals(ArrayList(), testSources)
assertContentEquals(sourcesDB.map { it.toView() }, testSources)
coVerify(exactly = 0) { api.sources() }
verify(exactly = 0) { db.sourcesQueries.sources().executeAsList() }
verify(atLeast = 1) { db.sourcesQueries.sources().executeAsList() }
}
@Test