浏览代码

Fix tests

len 8 年之前
父节点
当前提交
eed295587d

+ 0 - 573
app/src/test/java/eu/kanade/tachiyomi/BackupTest.java

@@ -1,573 +0,0 @@
-package eu.kanade.tachiyomi;
-
-import android.app.Application;
-import android.os.Build;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import eu.kanade.tachiyomi.data.backup.BackupManager;
-import eu.kanade.tachiyomi.data.database.DatabaseHelper;
-import eu.kanade.tachiyomi.data.database.models.Category;
-import eu.kanade.tachiyomi.data.database.models.Chapter;
-import eu.kanade.tachiyomi.data.database.models.Manga;
-import eu.kanade.tachiyomi.data.database.models.MangaCategory;
-import eu.kanade.tachiyomi.data.database.models.MangaSync;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
-@RunWith(CustomRobolectricGradleTestRunner.class)
-public class BackupTest {
-
-    DatabaseHelper db;
-    BackupManager backupManager;
-    Gson gson;
-    JsonObject root;
-
-    @Before
-    public void setup() {
-        Application app = RuntimeEnvironment.application;
-        db = new DatabaseHelper(app);
-        backupManager = new BackupManager(db);
-        gson = new Gson();
-        root = new JsonObject();
-    }
-
-    @Test
-    public void testRestoreCategory() {
-        String catName = "cat";
-        root = createRootJson(null, toJson(createCategories(catName)));
-        backupManager.restoreFromJson(root);
-
-        List<Category> dbCats = db.getCategories().executeAsBlocking();
-        assertThat(dbCats).hasSize(1);
-        assertThat(dbCats.get(0).name).isEqualTo(catName);
-    }
-
-    @Test
-    public void testRestoreEmptyCategory() {
-        root = createRootJson(null, toJson(new ArrayList<>()));
-        backupManager.restoreFromJson(root);
-        List<Category> dbCats = db.getCategories().executeAsBlocking();
-        assertThat(dbCats).isEmpty();
-    }
-
-    @Test
-    public void testRestoreExistingCategory() {
-        String catName = "cat";
-        db.insertCategory(createCategory(catName)).executeAsBlocking();
-
-        root = createRootJson(null, toJson(createCategories(catName)));
-        backupManager.restoreFromJson(root);
-
-        List<Category> dbCats = db.getCategories().executeAsBlocking();
-        assertThat(dbCats).hasSize(1);
-        assertThat(dbCats.get(0).name).isEqualTo(catName);
-    }
-
-    @Test
-    public void testRestoreCategories() {
-        root = createRootJson(null, toJson(createCategories("cat", "cat2", "cat3")));
-        backupManager.restoreFromJson(root);
-
-        List<Category> dbCats = db.getCategories().executeAsBlocking();
-        assertThat(dbCats).hasSize(3);
-    }
-
-    @Test
-    public void testRestoreExistingCategories() {
-        db.insertCategories(createCategories("cat", "cat2")).executeAsBlocking();
-
-        root = createRootJson(null, toJson(createCategories("cat", "cat2", "cat3")));
-        backupManager.restoreFromJson(root);
-
-        List<Category> dbCats = db.getCategories().executeAsBlocking();
-        assertThat(dbCats).hasSize(3);
-    }
-
-    @Test
-    public void testRestoreExistingCategoriesAlt() {
-        db.insertCategories(createCategories("cat", "cat2", "cat3")).executeAsBlocking();
-
-        root = createRootJson(null, toJson(createCategories("cat", "cat2")));
-        backupManager.restoreFromJson(root);
-
-        List<Category> dbCats = db.getCategories().executeAsBlocking();
-        assertThat(dbCats).hasSize(3);
-    }
-
-    @Test
-    public void testRestoreManga() {
-        String mangaName = "title";
-        List<Manga> mangas = createMangas(mangaName);
-        List<JsonElement> elements = new ArrayList<>();
-        for (Manga manga : mangas) {
-            JsonObject entry = new JsonObject();
-            entry.add("manga", toJson(manga));
-            elements.add(entry);
-        }
-        root = createRootJson(toJson(elements), null);
-        backupManager.restoreFromJson(root);
-
-        List<Manga> dbMangas = db.getMangas().executeAsBlocking();
-        assertThat(dbMangas).hasSize(1);
-        assertThat(dbMangas.get(0).title).isEqualTo(mangaName);
-    }
-
-    @Test
-    public void testRestoreExistingManga() {
-        String mangaName = "title";
-        Manga manga = createManga(mangaName);
-
-        db.insertManga(manga).executeAsBlocking();
-
-        List<JsonElement> elements = new ArrayList<>();
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        elements.add(entry);
-
-        root = createRootJson(toJson(elements), null);
-        backupManager.restoreFromJson(root);
-
-        List<Manga> dbMangas = db.getMangas().executeAsBlocking();
-        assertThat(dbMangas).hasSize(1);
-    }
-
-    @Test
-    public void testRestoreExistingMangaWithUpdatedFields() {
-        // Store a manga in db
-        String mangaName = "title";
-        String updatedThumbnailUrl = "updated thumbnail url";
-        Manga manga = createManga(mangaName);
-        manga.chapter_flags = 1024;
-        manga.thumbnail_url = updatedThumbnailUrl;
-        db.insertManga(manga).executeAsBlocking();
-
-        // Add an entry for a new manga with different attributes
-        manga = createManga(mangaName);
-        manga.chapter_flags = 512;
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-
-        // Append the entry to the backup list
-        List<JsonElement> elements = new ArrayList<>();
-        elements.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(elements), null);
-        backupManager.restoreFromJson(root);
-
-        List<Manga> dbMangas = db.getMangas().executeAsBlocking();
-        assertThat(dbMangas).hasSize(1);
-        assertThat(dbMangas.get(0).thumbnail_url).isEqualTo(updatedThumbnailUrl);
-        assertThat(dbMangas.get(0).chapter_flags).isEqualTo(512);
-    }
-
-    @Test
-    public void testRestoreChaptersForManga() {
-        // Create a manga and 3 chapters
-        Manga manga = createManga("title");
-        manga.id = 1L;
-        List<Chapter> chapters = createChapters(manga, "1", "2", "3");
-
-        // Add an entry for the manga
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        entry.add("chapters", toJson(chapters));
-
-        // Append the entry to the backup list
-        List<JsonElement> mangas = new ArrayList<>();
-        mangas.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(mangas), null);
-        backupManager.restoreFromJson(root);
-
-        Manga dbManga = db.getManga(1).executeAsBlocking();
-        assertThat(dbManga).isNotNull();
-
-        List<Chapter> dbChapters = db.getChapters(dbManga).executeAsBlocking();
-        assertThat(dbChapters).hasSize(3);
-    }
-
-    @Test
-    public void testRestoreChaptersForExistingManga() {
-        long mangaId = 3;
-        // Create a manga and 3 chapters
-        Manga manga = createManga("title");
-        manga.id = mangaId;
-        List<Chapter> chapters = createChapters(manga, "1", "2", "3");
-        db.insertManga(manga).executeAsBlocking();
-
-        // Add an entry for the manga
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        entry.add("chapters", toJson(chapters));
-
-        // Append the entry to the backup list
-        List<JsonElement> mangas = new ArrayList<>();
-        mangas.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(mangas), null);
-        backupManager.restoreFromJson(root);
-
-        Manga dbManga = db.getManga(mangaId).executeAsBlocking();
-        assertThat(dbManga).isNotNull();
-
-        List<Chapter> dbChapters = db.getChapters(dbManga).executeAsBlocking();
-        assertThat(dbChapters).hasSize(3);
-    }
-
-    @Test
-    public void testRestoreExistingChaptersForExistingManga() {
-        long mangaId = 5;
-        // Store a manga and 3 chapters
-        Manga manga = createManga("title");
-        manga.id = mangaId;
-        List<Chapter> chapters = createChapters(manga, "1", "2", "3");
-        db.insertManga(manga).executeAsBlocking();
-        db.insertChapters(chapters).executeAsBlocking();
-
-        // The backup contains a existing chapter and a new one, so it should have 4 chapters
-        chapters = createChapters(manga, "3", "4");
-
-        // Add an entry for the manga
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        entry.add("chapters", toJson(chapters));
-
-        // Append the entry to the backup list
-        List<JsonElement> mangas = new ArrayList<>();
-        mangas.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(mangas), null);
-        backupManager.restoreFromJson(root);
-
-        Manga dbManga = db.getManga(mangaId).executeAsBlocking();
-        assertThat(dbManga).isNotNull();
-
-        List<Chapter> dbChapters = db.getChapters(dbManga).executeAsBlocking();
-        assertThat(dbChapters).hasSize(4);
-    }
-
-    @Test
-    public void testRestoreCategoriesForManga() {
-        // Create a manga
-        Manga manga = createManga("title");
-
-        // Create categories
-        List<Category> categories = createCategories("cat1", "cat2", "cat3");
-
-        // Add an entry for the manga
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        entry.add("categories", toJson(createStringCategories("cat1")));
-
-        // Append the entry to the backup list
-        List<JsonElement> mangas = new ArrayList<>();
-        mangas.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(mangas), toJson(categories));
-        backupManager.restoreFromJson(root);
-
-        Manga dbManga = db.getManga(1).executeAsBlocking();
-        assertThat(dbManga).isNotNull();
-
-        assertThat(db.getCategoriesForManga(dbManga).executeAsBlocking())
-                .hasSize(1)
-                .contains(Category.create("cat1"))
-                .doesNotContain(Category.create("cat2"));
-    }
-
-    @Test
-    public void testRestoreCategoriesForExistingManga() {
-        // Store a manga
-        Manga manga = createManga("title");
-        db.insertManga(manga).executeAsBlocking();
-
-        // Create categories
-        List<Category> categories = createCategories("cat1", "cat2", "cat3");
-
-        // Add an entry for the manga
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        entry.add("categories", toJson(createStringCategories("cat1")));
-
-        // Append the entry to the backup list
-        List<JsonElement> mangas = new ArrayList<>();
-        mangas.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(mangas), toJson(categories));
-        backupManager.restoreFromJson(root);
-
-        Manga dbManga = db.getManga(1).executeAsBlocking();
-        assertThat(dbManga).isNotNull();
-
-        assertThat(db.getCategoriesForManga(dbManga).executeAsBlocking())
-                .hasSize(1)
-                .contains(Category.create("cat1"))
-                .doesNotContain(Category.create("cat2"));
-    }
-
-    @Test
-    public void testRestoreMultipleCategoriesForManga() {
-        // Create a manga
-        Manga manga = createManga("title");
-
-        // Create categories
-        List<Category> categories = createCategories("cat1", "cat2", "cat3");
-
-        // Add an entry for the manga
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        entry.add("categories", toJson(createStringCategories("cat1", "cat3")));
-
-        // Append the entry to the backup list
-        List<JsonElement> mangas = new ArrayList<>();
-        mangas.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(mangas), toJson(categories));
-        backupManager.restoreFromJson(root);
-
-        Manga dbManga = db.getManga(1).executeAsBlocking();
-        assertThat(dbManga).isNotNull();
-
-        assertThat(db.getCategoriesForManga(dbManga).executeAsBlocking())
-                .hasSize(2)
-                .contains(Category.create("cat1"), Category.create("cat3"))
-                .doesNotContain(Category.create("cat2"));
-    }
-
-    @Test
-    public void testRestoreMultipleCategoriesForExistingMangaAndCategory() {
-        // Store a manga and a category
-        Manga manga = createManga("title");
-        manga.id = 1L;
-        db.insertManga(manga).executeAsBlocking();
-
-        Category cat = createCategory("cat1");
-        cat.id = 1;
-        db.insertCategory(cat).executeAsBlocking();
-        db.insertMangaCategory(MangaCategory.create(manga, cat)).executeAsBlocking();
-
-        // Create categories
-        List<Category> categories = createCategories("cat1", "cat2", "cat3");
-
-        // Add an entry for the manga
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        entry.add("categories", toJson(createStringCategories("cat1", "cat2")));
-
-        // Append the entry to the backup list
-        List<JsonElement> mangas = new ArrayList<>();
-        mangas.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(mangas), toJson(categories));
-        backupManager.restoreFromJson(root);
-
-        Manga dbManga = db.getManga(1).executeAsBlocking();
-        assertThat(dbManga).isNotNull();
-
-        assertThat(db.getCategoriesForManga(dbManga).executeAsBlocking())
-                .hasSize(2)
-                .contains(Category.create("cat1"), Category.create("cat2"))
-                .doesNotContain(Category.create("cat3"));
-    }
-
-    @Test
-    public void testRestoreSyncForManga() {
-        // Create a manga and mangaSync
-        Manga manga = createManga("title");
-        manga.id = 1L;
-
-        List<MangaSync> mangaSync = createMangaSync(manga, 1, 2, 3);
-
-        // Add an entry for the manga
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        entry.add("sync", toJson(mangaSync));
-
-        // Append the entry to the backup list
-        List<JsonElement> mangas = new ArrayList<>();
-        mangas.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(mangas), null);
-        backupManager.restoreFromJson(root);
-
-        Manga dbManga = db.getManga(1).executeAsBlocking();
-        assertThat(dbManga).isNotNull();
-
-        List<MangaSync> dbSync = db.getMangasSync(dbManga).executeAsBlocking();
-        assertThat(dbSync).hasSize(3);
-    }
-
-    @Test
-    public void testRestoreSyncForExistingManga() {
-        long mangaId = 3;
-        // Create a manga and 3 sync
-        Manga manga = createManga("title");
-        manga.id = mangaId;
-        List<MangaSync> mangaSync = createMangaSync(manga, 1, 2, 3);
-        db.insertManga(manga).executeAsBlocking();
-
-        // Add an entry for the manga
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        entry.add("sync", toJson(mangaSync));
-
-        // Append the entry to the backup list
-        List<JsonElement> mangas = new ArrayList<>();
-        mangas.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(mangas), null);
-        backupManager.restoreFromJson(root);
-
-        Manga dbManga = db.getManga(mangaId).executeAsBlocking();
-        assertThat(dbManga).isNotNull();
-
-        List<MangaSync> dbSync = db.getMangasSync(dbManga).executeAsBlocking();
-        assertThat(dbSync).hasSize(3);
-    }
-
-    @Test
-    public void testRestoreExistingSyncForExistingManga() {
-        long mangaId = 5;
-        // Store a manga and 3 sync
-        Manga manga = createManga("title");
-        manga.id = mangaId;
-        List<MangaSync> mangaSync = createMangaSync(manga, 1, 2, 3);
-        db.insertManga(manga).executeAsBlocking();
-        db.insertMangasSync(mangaSync).executeAsBlocking();
-
-        // The backup contains a existing sync and a new one, so it should have 4 sync
-        mangaSync = createMangaSync(manga, 3, 4);
-
-        // Add an entry for the manga
-        JsonObject entry = new JsonObject();
-        entry.add("manga", toJson(manga));
-        entry.add("sync", toJson(mangaSync));
-
-        // Append the entry to the backup list
-        List<JsonElement> mangas = new ArrayList<>();
-        mangas.add(entry);
-
-        // Restore from json
-        root = createRootJson(toJson(mangas), null);
-        backupManager.restoreFromJson(root);
-
-        Manga dbManga = db.getManga(mangaId).executeAsBlocking();
-        assertThat(dbManga).isNotNull();
-
-        List<MangaSync> dbSync = db.getMangasSync(dbManga).executeAsBlocking();
-        assertThat(dbSync).hasSize(4);
-    }
-
-    private JsonObject createRootJson(JsonElement mangas, JsonElement categories) {
-        JsonObject root = new JsonObject();
-        if (mangas != null)
-            root.add("mangas", mangas);
-        if (categories != null)
-            root.add("categories", categories);
-        return root;
-    }
-
-    private Category createCategory(String name) {
-        Category c = new Category();
-        c.name = name;
-        return c;
-    }
-
-    private List<Category> createCategories(String... names) {
-        List<Category> cats = new ArrayList<>();
-        for (String name : names) {
-            cats.add(createCategory(name));
-        }
-        return cats;
-    }
-
-    private List<String> createStringCategories(String... names) {
-        List<String> cats = new ArrayList<>();
-        for (String name : names) {
-            cats.add(name);
-        }
-        return cats;
-    }
-
-    private Manga createManga(String title) {
-        Manga m = new Manga();
-        m.title = title;
-        m.author = "";
-        m.artist = "";
-        m.thumbnail_url = "";
-        m.genre = "a list of genres";
-        m.description = "long description";
-        m.url = "url to manga";
-        m.favorite = true;
-        m.source = 1;
-        return m;
-    }
-
-    private List<Manga> createMangas(String... titles) {
-        List<Manga> mangas = new ArrayList<>();
-        for (String title : titles) {
-            mangas.add(createManga(title));
-        }
-        return mangas;
-    }
-
-    private Chapter createChapter(Manga manga, String url) {
-        Chapter c = Chapter.create();
-        c.url = url;
-        c.name = url;
-        c.manga_id = manga.id;
-        return c;
-    }
-
-    private List<Chapter> createChapters(Manga manga, String... urls) {
-        List<Chapter> chapters = new ArrayList<>();
-        for (String url : urls) {
-            chapters.add(createChapter(manga, url));
-        }
-        return chapters;
-    }
-
-    private MangaSync createMangaSync(Manga manga, int syncId) {
-        MangaSync m = MangaSync.create();
-        m.manga_id = manga.id;
-        m.sync_id = syncId;
-        m.title = "title";
-        return m;
-    }
-
-    private List<MangaSync> createMangaSync(Manga manga, Integer... syncIds) {
-        List<MangaSync> ms = new ArrayList<>();
-        for (int title : syncIds) {
-            ms.add(createMangaSync(manga, title));
-        }
-        return ms;
-    }
-
-    private JsonElement toJson(Object element) {
-        return gson.toJsonTree(element);
-    }
-
-}

+ 0 - 115
app/src/test/java/eu/kanade/tachiyomi/CategoryTest.java

@@ -1,115 +0,0 @@
-package eu.kanade.tachiyomi;
-
-import android.app.Application;
-import android.os.Build;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
-
-import java.util.List;
-
-import eu.kanade.tachiyomi.data.database.DatabaseHelper;
-import eu.kanade.tachiyomi.data.database.models.Category;
-import eu.kanade.tachiyomi.data.database.models.Manga;
-import eu.kanade.tachiyomi.data.database.models.MangaCategory;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
-@RunWith(CustomRobolectricGradleTestRunner.class)
-public class CategoryTest {
-
-    DatabaseHelper db;
-
-    @Before
-    public void setup() {
-        Application app = RuntimeEnvironment.application;
-        db = new DatabaseHelper(app);
-
-        // Create 5 mangas
-        createManga("a");
-        createManga("b");
-        createManga("c");
-        createManga("d");
-        createManga("e");
-    }
-
-    @Test
-    public void testHasCategories() {
-        // Create 2 categories
-        createCategory("Reading");
-        createCategory("Hold");
-
-        List<Category> categories = db.getCategories().executeAsBlocking();
-        assertThat(categories).hasSize(2);
-    }
-
-    @Test
-    public void testHasLibraryMangas() {
-        List<Manga> mangas = db.getLibraryMangas().executeAsBlocking();
-        assertThat(mangas).hasSize(5);
-    }
-
-    @Test
-    public void testHasCorrectFavorites() {
-        Manga m = new Manga();
-        m.title = "title";
-        m.author = "";
-        m.artist = "";
-        m.thumbnail_url = "";
-        m.genre = "a list of genres";
-        m.description = "long description";
-        m.url = "url to manga";
-        m.favorite = false;
-        db.insertManga(m).executeAsBlocking();
-        List<Manga> mangas = db.getLibraryMangas().executeAsBlocking();
-        assertThat(mangas).hasSize(5);
-    }
-
-    @Test
-    public void testMangaInCategory() {
-        // Create 2 categories
-        createCategory("Reading");
-        createCategory("Hold");
-
-        // It should not have 0 as id
-        Category c = db.getCategories().executeAsBlocking().get(0);
-        assertThat(c.id).isNotZero();
-
-        // Add a manga to a category
-        Manga m = db.getMangas().executeAsBlocking().get(0);
-        MangaCategory mc = MangaCategory.create(m, c);
-        db.insertMangaCategory(mc).executeAsBlocking();
-
-        // Get mangas from library and assert manga category is the same
-        List<Manga> mangas = db.getLibraryMangas().executeAsBlocking();
-        for (Manga manga : mangas) {
-            if (manga.id.equals(m.id)) {
-                assertThat(manga.category).isEqualTo(c.id);
-            }
-        }
-    }
-
-    private void createManga(String title) {
-        Manga m = new Manga();
-        m.title = title;
-        m.author = "";
-        m.artist = "";
-        m.thumbnail_url = "";
-        m.genre = "a list of genres";
-        m.description = "long description";
-        m.url = "url to manga";
-        m.favorite = true;
-        db.insertManga(m).executeAsBlocking();
-    }
-
-    private void createCategory(String name) {
-        Category c = new Category();
-        c.name = name;
-        db.insertCategory(c).executeAsBlocking();
-    }
-
-}

+ 109 - 0
app/src/test/java/eu/kanade/tachiyomi/CategoryTest.kt

@@ -0,0 +1,109 @@
+package eu.kanade.tachiyomi
+
+import android.os.Build
+import eu.kanade.tachiyomi.data.database.DatabaseHelper
+import eu.kanade.tachiyomi.data.database.models.CategoryImpl
+import eu.kanade.tachiyomi.data.database.models.Manga
+import eu.kanade.tachiyomi.data.database.models.MangaCategory
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RuntimeEnvironment
+import org.robolectric.annotation.Config
+
+@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
+@RunWith(CustomRobolectricGradleTestRunner::class)
+class CategoryTest {
+
+    lateinit var db: DatabaseHelper
+
+    @Before
+    fun setup() {
+        val app = RuntimeEnvironment.application
+        db = DatabaseHelper(app)
+
+        // Create 5 manga
+        createManga("a")
+        createManga("b")
+        createManga("c")
+        createManga("d")
+        createManga("e")
+    }
+
+    @Test
+    fun testHasCategories() {
+        // Create 2 categories
+        createCategory("Reading")
+        createCategory("Hold")
+
+        val categories = db.getCategories().executeAsBlocking()
+        assertThat(categories).hasSize(2)
+    }
+
+    @Test
+    fun testHasLibraryMangas() {
+        val mangas = db.getLibraryMangas().executeAsBlocking()
+        assertThat(mangas).hasSize(5)
+    }
+
+    @Test
+    fun testHasCorrectFavorites() {
+        val m = Manga.create(0)
+        m.title = "title"
+        m.author = ""
+        m.artist = ""
+        m.thumbnail_url = ""
+        m.genre = "a list of genres"
+        m.description = "long description"
+        m.url = "url to manga"
+        m.favorite = false
+        db.insertManga(m).executeAsBlocking()
+        val mangas = db.getLibraryMangas().executeAsBlocking()
+        assertThat(mangas).hasSize(5)
+    }
+
+    @Test
+    fun testMangaInCategory() {
+        // Create 2 categories
+        createCategory("Reading")
+        createCategory("Hold")
+
+        // It should not have 0 as id
+        val c = db.getCategories().executeAsBlocking()[0]
+        assertThat(c.id).isNotZero()
+
+        // Add a manga to a category
+        val m = db.getMangas().executeAsBlocking()[0]
+        val mc = MangaCategory.create(m, c)
+        db.insertMangaCategory(mc).executeAsBlocking()
+
+        // Get mangas from library and assert manga category is the same
+        val mangas = db.getLibraryMangas().executeAsBlocking()
+        for (manga in mangas) {
+            if (manga.id == m.id) {
+                assertThat(manga.category).isEqualTo(c.id)
+            }
+        }
+    }
+
+    private fun createManga(title: String) {
+        val m = Manga.create(0)
+        m.title = title
+        m.author = ""
+        m.artist = ""
+        m.thumbnail_url = ""
+        m.genre = "a list of genres"
+        m.description = "long description"
+        m.url = "url to manga"
+        m.favorite = true
+        db.insertManga(m).executeAsBlocking()
+    }
+
+    private fun createCategory(name: String) {
+        val c = CategoryImpl()
+        c.name = name
+        db.insertCategory(c).executeAsBlocking()
+    }
+
+}

+ 1 - 1
app/src/test/java/eu/kanade/tachiyomi/ChapterRecognitionTest.kt

@@ -43,7 +43,7 @@ class ChapterRecognitionTest {
      * Called before test
      */
     @Before fun setup() {
-        manga = Manga().apply { title = "random" }
+        manga = Manga.create(0).apply { title = "random" }
         chapter = Chapter.create()
     }
 

+ 0 - 12
app/src/test/java/eu/kanade/tachiyomi/TestApp.kt

@@ -1,19 +1,7 @@
 package eu.kanade.tachiyomi
 
-import eu.kanade.tachiyomi.injection.component.AppComponent
-import eu.kanade.tachiyomi.injection.component.DaggerAppComponent
-import eu.kanade.tachiyomi.injection.module.AppModule
-import eu.kanade.tachiyomi.injection.module.TestDataModule
-
 open class TestApp : App() {
 
-    override fun createAppComponent(): AppComponent {
-        return DaggerAppComponent.builder()
-                .appModule(AppModule(this))
-                .dataModule(TestDataModule())
-                .build()
-    }
-
     override fun setupAcra() {
         // Do nothing
     }

+ 568 - 0
app/src/test/java/eu/kanade/tachiyomi/data/backup/BackupTest.kt

@@ -0,0 +1,568 @@
+package eu.kanade.tachiyomi.data.backup
+
+import android.os.Build
+import com.google.gson.Gson
+import com.google.gson.JsonElement
+import com.google.gson.JsonObject
+import eu.kanade.tachiyomi.BuildConfig
+import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
+import eu.kanade.tachiyomi.data.database.DatabaseHelper
+import eu.kanade.tachiyomi.data.database.models.*
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RuntimeEnvironment
+import org.robolectric.annotation.Config
+import uy.kohesive.injekt.injectLazy
+import java.util.*
+
+@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
+@RunWith(CustomRobolectricGradleTestRunner::class)
+class BackupTest {
+
+    val gson: Gson by injectLazy()
+
+    lateinit var db: DatabaseHelper
+
+    lateinit var backupManager: BackupManager
+
+    lateinit var root: JsonObject
+
+    @Before
+    fun setup() {
+        val app = RuntimeEnvironment.application
+        db = DatabaseHelper(app)
+        backupManager = BackupManager(db)
+        root = JsonObject()
+    }
+
+    @Test
+    fun testRestoreCategory() {
+        val catName = "cat"
+        root = createRootJson(null, toJson(createCategories(catName)))
+        backupManager.restoreFromJson(root)
+
+        val dbCats = db.getCategories().executeAsBlocking()
+        assertThat(dbCats).hasSize(1)
+        assertThat(dbCats[0].name).isEqualTo(catName)
+    }
+
+    @Test
+    fun testRestoreEmptyCategory() {
+        root = createRootJson(null, toJson(ArrayList<Any>()))
+        backupManager.restoreFromJson(root)
+        val dbCats = db.getCategories().executeAsBlocking()
+        assertThat(dbCats).isEmpty()
+    }
+
+    @Test
+    fun testRestoreExistingCategory() {
+        val catName = "cat"
+        db.insertCategory(createCategory(catName)).executeAsBlocking()
+
+        root = createRootJson(null, toJson(createCategories(catName)))
+        backupManager.restoreFromJson(root)
+
+        val dbCats = db.getCategories().executeAsBlocking()
+        assertThat(dbCats).hasSize(1)
+        assertThat(dbCats[0].name).isEqualTo(catName)
+    }
+
+    @Test
+    fun testRestoreCategories() {
+        root = createRootJson(null, toJson(createCategories("cat", "cat2", "cat3")))
+        backupManager.restoreFromJson(root)
+
+        val dbCats = db.getCategories().executeAsBlocking()
+        assertThat(dbCats).hasSize(3)
+    }
+
+    @Test
+    fun testRestoreExistingCategories() {
+        db.insertCategories(createCategories("cat", "cat2")).executeAsBlocking()
+
+        root = createRootJson(null, toJson(createCategories("cat", "cat2", "cat3")))
+        backupManager.restoreFromJson(root)
+
+        val dbCats = db.getCategories().executeAsBlocking()
+        assertThat(dbCats).hasSize(3)
+    }
+
+    @Test
+    fun testRestoreExistingCategoriesAlt() {
+        db.insertCategories(createCategories("cat", "cat2", "cat3")).executeAsBlocking()
+
+        root = createRootJson(null, toJson(createCategories("cat", "cat2")))
+        backupManager.restoreFromJson(root)
+
+        val dbCats = db.getCategories().executeAsBlocking()
+        assertThat(dbCats).hasSize(3)
+    }
+
+    @Test
+    fun testRestoreManga() {
+        val mangaName = "title"
+        val mangas = createMangas(mangaName)
+        val elements = ArrayList<JsonElement>()
+        for (manga in mangas) {
+            val entry = JsonObject()
+            entry.add("manga", toJson(manga))
+            elements.add(entry)
+        }
+        root = createRootJson(toJson(elements), null)
+        backupManager.restoreFromJson(root)
+
+        val dbMangas = db.getMangas().executeAsBlocking()
+        assertThat(dbMangas).hasSize(1)
+        assertThat(dbMangas[0].title).isEqualTo(mangaName)
+    }
+
+    @Test
+    fun testRestoreExistingManga() {
+        val mangaName = "title"
+        val manga = createManga(mangaName)
+
+        db.insertManga(manga).executeAsBlocking()
+
+        val elements = ArrayList<JsonElement>()
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        elements.add(entry)
+
+        root = createRootJson(toJson(elements), null)
+        backupManager.restoreFromJson(root)
+
+        val dbMangas = db.getMangas().executeAsBlocking()
+        assertThat(dbMangas).hasSize(1)
+    }
+
+    @Test
+    fun testRestoreExistingMangaWithUpdatedFields() {
+        // Store a manga in db
+        val mangaName = "title"
+        val updatedThumbnailUrl = "updated thumbnail url"
+        var manga = createManga(mangaName)
+        manga.chapter_flags = 1024
+        manga.thumbnail_url = updatedThumbnailUrl
+        db.insertManga(manga).executeAsBlocking()
+
+        // Add an entry for a new manga with different attributes
+        manga = createManga(mangaName)
+        manga.chapter_flags = 512
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+
+        // Append the entry to the backup list
+        val elements = ArrayList<JsonElement>()
+        elements.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(elements), null)
+        backupManager.restoreFromJson(root)
+
+        val dbMangas = db.getMangas().executeAsBlocking()
+        assertThat(dbMangas).hasSize(1)
+        assertThat(dbMangas[0].thumbnail_url).isEqualTo(updatedThumbnailUrl)
+        assertThat(dbMangas[0].chapter_flags).isEqualTo(512)
+    }
+
+    @Test
+    fun testRestoreChaptersForManga() {
+        // Create a manga and 3 chapters
+        val manga = createManga("title")
+        manga.id = 1L
+        val chapters = createChapters(manga, "1", "2", "3")
+
+        // Add an entry for the manga
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        entry.add("chapters", toJson(chapters))
+
+        // Append the entry to the backup list
+        val mangas = ArrayList<JsonElement>()
+        mangas.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(mangas), null)
+        backupManager.restoreFromJson(root)
+
+        val dbManga = db.getManga(1).executeAsBlocking()
+        assertThat(dbManga).isNotNull()
+
+        val dbChapters = db.getChapters(dbManga!!).executeAsBlocking()
+        assertThat(dbChapters).hasSize(3)
+    }
+
+    @Test
+    fun testRestoreChaptersForExistingManga() {
+        val mangaId: Long = 3
+        // Create a manga and 3 chapters
+        val manga = createManga("title")
+        manga.id = mangaId
+        val chapters = createChapters(manga, "1", "2", "3")
+        db.insertManga(manga).executeAsBlocking()
+
+        // Add an entry for the manga
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        entry.add("chapters", toJson(chapters))
+
+        // Append the entry to the backup list
+        val mangas = ArrayList<JsonElement>()
+        mangas.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(mangas), null)
+        backupManager.restoreFromJson(root)
+
+        val dbManga = db.getManga(mangaId).executeAsBlocking()
+        assertThat(dbManga).isNotNull()
+
+        val dbChapters = db.getChapters(dbManga!!).executeAsBlocking()
+        assertThat(dbChapters).hasSize(3)
+    }
+
+    @Test
+    fun testRestoreExistingChaptersForExistingManga() {
+        val mangaId: Long = 5
+        // Store a manga and 3 chapters
+        val manga = createManga("title")
+        manga.id = mangaId
+        var chapters = createChapters(manga, "1", "2", "3")
+        db.insertManga(manga).executeAsBlocking()
+        db.insertChapters(chapters).executeAsBlocking()
+
+        // The backup contains a existing chapter and a new one, so it should have 4 chapters
+        chapters = createChapters(manga, "3", "4")
+
+        // Add an entry for the manga
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        entry.add("chapters", toJson(chapters))
+
+        // Append the entry to the backup list
+        val mangas = ArrayList<JsonElement>()
+        mangas.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(mangas), null)
+        backupManager.restoreFromJson(root)
+
+        val dbManga = db.getManga(mangaId).executeAsBlocking()
+        assertThat(dbManga).isNotNull()
+
+        val dbChapters = db.getChapters(dbManga!!).executeAsBlocking()
+        assertThat(dbChapters).hasSize(4)
+    }
+
+    @Test
+    fun testRestoreCategoriesForManga() {
+        // Create a manga
+        val manga = createManga("title")
+
+        // Create categories
+        val categories = createCategories("cat1", "cat2", "cat3")
+
+        // Add an entry for the manga
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        entry.add("categories", toJson(createStringCategories("cat1")))
+
+        // Append the entry to the backup list
+        val mangas = ArrayList<JsonElement>()
+        mangas.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(mangas), toJson(categories))
+        backupManager.restoreFromJson(root)
+
+        val dbManga = db.getManga(1).executeAsBlocking()
+        assertThat(dbManga).isNotNull()
+
+        val result = db.getCategoriesForManga(dbManga!!).executeAsBlocking()
+
+        assertThat(result).hasSize(1)
+        assertThat(result).contains(Category.create("cat1"))
+        assertThat(result).doesNotContain(Category.create("cat2"))
+    }
+
+    @Test
+    fun testRestoreCategoriesForExistingManga() {
+        // Store a manga
+        val manga = createManga("title")
+        db.insertManga(manga).executeAsBlocking()
+
+        // Create categories
+        val categories = createCategories("cat1", "cat2", "cat3")
+
+        // Add an entry for the manga
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        entry.add("categories", toJson(createStringCategories("cat1")))
+
+        // Append the entry to the backup list
+        val mangas = ArrayList<JsonElement>()
+        mangas.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(mangas), toJson(categories))
+        backupManager.restoreFromJson(root)
+
+        val dbManga = db.getManga(1).executeAsBlocking()
+        assertThat(dbManga).isNotNull()
+
+        val result = db.getCategoriesForManga(dbManga!!).executeAsBlocking()
+
+        assertThat(result).hasSize(1)
+        assertThat(result).contains(Category.create("cat1"))
+        assertThat(result).doesNotContain(Category.create("cat2"))
+    }
+
+    @Test
+    fun testRestoreMultipleCategoriesForManga() {
+        // Create a manga
+        val manga = createManga("title")
+
+        // Create categories
+        val categories = createCategories("cat1", "cat2", "cat3")
+
+        // Add an entry for the manga
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        entry.add("categories", toJson(createStringCategories("cat1", "cat3")))
+
+        // Append the entry to the backup list
+        val mangas = ArrayList<JsonElement>()
+        mangas.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(mangas), toJson(categories))
+        backupManager.restoreFromJson(root)
+
+        val dbManga = db.getManga(1).executeAsBlocking()
+        assertThat(dbManga).isNotNull()
+
+        val result = db.getCategoriesForManga(dbManga!!).executeAsBlocking()
+
+        assertThat(result).hasSize(2)
+        assertThat(result).contains(Category.create("cat1"), Category.create("cat3"))
+        assertThat(result).doesNotContain(Category.create("cat2"))
+    }
+
+    @Test
+    fun testRestoreMultipleCategoriesForExistingMangaAndCategory() {
+        // Store a manga and a category
+        val manga = createManga("title")
+        manga.id = 1L
+        db.insertManga(manga).executeAsBlocking()
+
+        val cat = createCategory("cat1")
+        cat.id = 1
+        db.insertCategory(cat).executeAsBlocking()
+        db.insertMangaCategory(MangaCategory.create(manga, cat)).executeAsBlocking()
+
+        // Create categories
+        val categories = createCategories("cat1", "cat2", "cat3")
+
+        // Add an entry for the manga
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        entry.add("categories", toJson(createStringCategories("cat1", "cat2")))
+
+        // Append the entry to the backup list
+        val mangas = ArrayList<JsonElement>()
+        mangas.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(mangas), toJson(categories))
+        backupManager.restoreFromJson(root)
+
+        val dbManga = db.getManga(1).executeAsBlocking()
+        assertThat(dbManga).isNotNull()
+
+        val result = db.getCategoriesForManga(dbManga!!).executeAsBlocking()
+
+        assertThat(result).hasSize(2)
+        assertThat(result).contains(Category.create("cat1"), Category.create("cat2"))
+        assertThat(result).doesNotContain(Category.create("cat3"))
+    }
+
+    @Test
+    fun testRestoreSyncForManga() {
+        // Create a manga and mangaSync
+        val manga = createManga("title")
+        manga.id = 1L
+
+        val mangaSync = createMangaSync(manga, 1, 2, 3)
+
+        // Add an entry for the manga
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        entry.add("sync", toJson(mangaSync))
+
+        // Append the entry to the backup list
+        val mangas = ArrayList<JsonElement>()
+        mangas.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(mangas), null)
+        backupManager.restoreFromJson(root)
+
+        val dbManga = db.getManga(1).executeAsBlocking()
+        assertThat(dbManga).isNotNull()
+
+        val dbSync = db.getMangasSync(dbManga!!).executeAsBlocking()
+        assertThat(dbSync).hasSize(3)
+    }
+
+    @Test
+    fun testRestoreSyncForExistingManga() {
+        val mangaId: Long = 3
+        // Create a manga and 3 sync
+        val manga = createManga("title")
+        manga.id = mangaId
+        val mangaSync = createMangaSync(manga, 1, 2, 3)
+        db.insertManga(manga).executeAsBlocking()
+
+        // Add an entry for the manga
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        entry.add("sync", toJson(mangaSync))
+
+        // Append the entry to the backup list
+        val mangas = ArrayList<JsonElement>()
+        mangas.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(mangas), null)
+        backupManager.restoreFromJson(root)
+
+        val dbManga = db.getManga(mangaId).executeAsBlocking()
+        assertThat(dbManga).isNotNull()
+
+        val dbSync = db.getMangasSync(dbManga!!).executeAsBlocking()
+        assertThat(dbSync).hasSize(3)
+    }
+
+    @Test
+    fun testRestoreExistingSyncForExistingManga() {
+        val mangaId: Long = 5
+        // Store a manga and 3 sync
+        val manga = createManga("title")
+        manga.id = mangaId
+        var mangaSync = createMangaSync(manga, 1, 2, 3)
+        db.insertManga(manga).executeAsBlocking()
+        db.insertMangasSync(mangaSync).executeAsBlocking()
+
+        // The backup contains a existing sync and a new one, so it should have 4 sync
+        mangaSync = createMangaSync(manga, 3, 4)
+
+        // Add an entry for the manga
+        val entry = JsonObject()
+        entry.add("manga", toJson(manga))
+        entry.add("sync", toJson(mangaSync))
+
+        // Append the entry to the backup list
+        val mangas = ArrayList<JsonElement>()
+        mangas.add(entry)
+
+        // Restore from json
+        root = createRootJson(toJson(mangas), null)
+        backupManager.restoreFromJson(root)
+
+        val dbManga = db.getManga(mangaId).executeAsBlocking()
+        assertThat(dbManga).isNotNull()
+
+        val dbSync = db.getMangasSync(dbManga!!).executeAsBlocking()
+        assertThat(dbSync).hasSize(4)
+    }
+
+    private fun createRootJson(mangas: JsonElement?, categories: JsonElement?): JsonObject {
+        val root = JsonObject()
+        if (mangas != null)
+            root.add("mangas", mangas)
+        if (categories != null)
+            root.add("categories", categories)
+        return root
+    }
+
+    private fun createCategory(name: String): Category {
+        val c = CategoryImpl()
+        c.name = name
+        return c
+    }
+
+    private fun createCategories(vararg names: String): List<Category> {
+        val cats = ArrayList<Category>()
+        for (name in names) {
+            cats.add(createCategory(name))
+        }
+        return cats
+    }
+
+    private fun createStringCategories(vararg names: String): List<String> {
+        val cats = ArrayList<String>()
+        for (name in names) {
+            cats.add(name)
+        }
+        return cats
+    }
+
+    private fun createManga(title: String): Manga {
+        val m = Manga.create(1)
+        m.title = title
+        m.author = ""
+        m.artist = ""
+        m.thumbnail_url = ""
+        m.genre = "a list of genres"
+        m.description = "long description"
+        m.url = "url to manga"
+        m.favorite = true
+        return m
+    }
+
+    private fun createMangas(vararg titles: String): List<Manga> {
+        val mangas = ArrayList<Manga>()
+        for (title in titles) {
+            mangas.add(createManga(title))
+        }
+        return mangas
+    }
+
+    private fun createChapter(manga: Manga, url: String): Chapter {
+        val c = Chapter.create()
+        c.url = url
+        c.name = url
+        c.manga_id = manga.id
+        return c
+    }
+
+    private fun createChapters(manga: Manga, vararg urls: String): List<Chapter> {
+        val chapters = ArrayList<Chapter>()
+        for (url in urls) {
+            chapters.add(createChapter(manga, url))
+        }
+        return chapters
+    }
+
+    private fun createMangaSync(manga: Manga, syncId: Int): MangaSync {
+        val m = MangaSync.create(syncId)
+        m.manga_id = manga.id!!
+        m.title = "title"
+        return m
+    }
+
+    private fun createMangaSync(manga: Manga, vararg syncIds: Int): List<MangaSync> {
+        val ms = ArrayList<MangaSync>()
+        for (title in syncIds) {
+            ms.add(createMangaSync(manga, title))
+        }
+        return ms
+    }
+
+    private fun toJson(element: Any): JsonElement {
+        return gson.toJsonTree(element)
+    }
+
+}

+ 0 - 115
app/src/test/java/eu/kanade/tachiyomi/data/library/LibraryUpdateServiceTest.java

@@ -1,115 +0,0 @@
-package eu.kanade.tachiyomi.data.library;
-
-import android.content.Context;
-import android.os.Build;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowApplication;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import eu.kanade.tachiyomi.BuildConfig;
-import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner;
-import eu.kanade.tachiyomi.data.database.models.Chapter;
-import eu.kanade.tachiyomi.data.database.models.Manga;
-import eu.kanade.tachiyomi.data.source.online.OnlineSource;
-import rx.Observable;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-@Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP)
-@RunWith(CustomRobolectricGradleTestRunner.class)
-public class LibraryUpdateServiceTest {
-
-    ShadowApplication app;
-    Context context;
-    LibraryUpdateService service;
-    OnlineSource source;
-
-    @Before
-    public void setup() {
-        app = ShadowApplication.getInstance();
-        context = app.getApplicationContext();
-        service = Robolectric.setupService(LibraryUpdateService.class);
-        source = mock(OnlineSource.class);
-        when(service.sourceManager.get(anyInt())).thenReturn(source);
-    }
-
-    @Test
-    public void testLifecycle() {
-        // Smoke test
-        Robolectric.buildService(LibraryUpdateService.class)
-                .attach()
-                .create()
-                .startCommand(0, 0)
-                .destroy()
-                .get();
-    }
-
-    @Test
-    public void testUpdateManga() {
-        Manga manga = createManga("/manga1").get(0);
-        manga.id = 1L;
-        service.db.insertManga(manga).executeAsBlocking();
-
-        List<Chapter> sourceChapters = createChapters("/chapter1", "/chapter2");
-
-        when(source.fetchChapterList(manga)).thenReturn(Observable.just(sourceChapters));
-
-        service.updateManga(manga).subscribe();
-
-        assertThat(service.db.getChapters(manga).executeAsBlocking()).hasSize(2);
-    }
-
-    @Test
-    public void testContinuesUpdatingWhenAMangaFails() {
-        List<Manga> favManga = createManga("/manga1", "/manga2", "/manga3");
-        service.db.insertMangas(favManga).executeAsBlocking();
-        favManga = service.db.getFavoriteMangas().executeAsBlocking();
-
-        List<Chapter> chapters = createChapters("/chapter1", "/chapter2");
-        List<Chapter> chapters3 = createChapters("/achapter1", "/achapter2");
-
-        // One of the updates will fail
-        when(source.fetchChapterList(favManga.get(0))).thenReturn(Observable.just(chapters));
-        when(source.fetchChapterList(favManga.get(1))).thenReturn(Observable.<List<Chapter>>error(new Exception()));
-        when(source.fetchChapterList(favManga.get(2))).thenReturn(Observable.just(chapters3));
-
-        service.updateMangaList(service.getMangaToUpdate(null)).subscribe();
-
-        // There are 3 network attempts and 2 insertions (1 request failed)
-        assertThat(service.db.getChapters(favManga.get(0)).executeAsBlocking()).hasSize(2);
-        assertThat(service.db.getChapters(favManga.get(1)).executeAsBlocking()).hasSize(0);
-        assertThat(service.db.getChapters(favManga.get(2)).executeAsBlocking()).hasSize(2);
-    }
-
-    private List<Chapter> createChapters(String... urls) {
-        List<Chapter> list = new ArrayList<>();
-        for (String url : urls) {
-            Chapter c = Chapter.create();
-            c.url = url;
-            c.name = url.substring(1);
-            list.add(c);
-        }
-        return list;
-    }
-
-    private List<Manga> createManga(String... urls) {
-        List<Manga> list = new ArrayList<>();
-        for (String url : urls) {
-            Manga m = Manga.create(url);
-            m.title = url.substring(1);
-            m.favorite = true;
-            list.add(m);
-        }
-        return list;
-    }
-}

+ 137 - 0
app/src/test/java/eu/kanade/tachiyomi/data/library/LibraryUpdateServiceTest.kt

@@ -0,0 +1,137 @@
+package eu.kanade.tachiyomi.data.library
+
+import android.app.Application
+import android.content.Context
+import android.os.Build
+import eu.kanade.tachiyomi.AppModule
+import eu.kanade.tachiyomi.BuildConfig
+import eu.kanade.tachiyomi.CustomRobolectricGradleTestRunner
+import eu.kanade.tachiyomi.data.database.models.Chapter
+import eu.kanade.tachiyomi.data.database.models.Manga
+import eu.kanade.tachiyomi.data.source.SourceManager
+import eu.kanade.tachiyomi.data.source.online.OnlineSource
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Matchers.anyInt
+import org.mockito.Mockito
+import org.mockito.Mockito.*
+import org.robolectric.Robolectric
+import org.robolectric.RuntimeEnvironment
+import org.robolectric.annotation.Config
+import rx.Observable
+import uy.kohesive.injekt.Injekt
+import uy.kohesive.injekt.api.InjektModule
+import uy.kohesive.injekt.api.InjektRegistrar
+import uy.kohesive.injekt.api.InjektScope
+import uy.kohesive.injekt.api.addSingleton
+import uy.kohesive.injekt.registry.default.DefaultRegistrar
+import java.util.*
+
+@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP))
+@RunWith(CustomRobolectricGradleTestRunner::class)
+class LibraryUpdateServiceTest {
+
+    lateinit var app: Application
+    lateinit var context: Context
+    lateinit var service: LibraryUpdateService
+    lateinit var source: OnlineSource
+
+    @Before
+    fun setup() {
+        app = RuntimeEnvironment.application
+        context = app.applicationContext
+
+        // Mock the source manager
+        val module = object : InjektModule {
+            override fun InjektRegistrar.registerInjectables() {
+                addSingleton(Mockito.mock(SourceManager::class.java, RETURNS_DEEP_STUBS))
+            }
+        }
+
+        // Restart injections for each test
+        Injekt = InjektScope(DefaultRegistrar())
+        Injekt.importModule(AppModule(app))
+        Injekt.importModule(module)
+
+        service = Robolectric.setupService(LibraryUpdateService::class.java)
+        source = mock(OnlineSource::class.java)
+        `when`(service.sourceManager.get(anyInt())).thenReturn(source)
+    }
+
+    @Test
+    fun testLifecycle() {
+        println(service.db)
+
+        // Smoke test
+        Robolectric.buildService(LibraryUpdateService::class.java)
+                .attach()
+                .create()
+                .startCommand(0, 0)
+                .destroy()
+                .get()
+    }
+
+    @Test
+    fun testUpdateManga() {
+        println(service.db)
+
+        val manga = createManga("/manga1")[0]
+        manga.id = 1L
+        service.db.insertManga(manga).executeAsBlocking()
+
+        val sourceChapters = createChapters("/chapter1", "/chapter2")
+
+        `when`(source.fetchChapterList(manga)).thenReturn(Observable.just(sourceChapters))
+
+        service.updateManga(manga).subscribe()
+
+        assertThat(service.db.getChapters(manga).executeAsBlocking()).hasSize(2)
+    }
+
+    @Test
+    fun testContinuesUpdatingWhenAMangaFails() {
+        var favManga = createManga("/manga1", "/manga2", "/manga3")
+        println(service.db)
+        service.db.insertMangas(favManga).executeAsBlocking()
+        favManga = service.db.getFavoriteMangas().executeAsBlocking()
+
+        val chapters = createChapters("/chapter1", "/chapter2")
+        val chapters3 = createChapters("/achapter1", "/achapter2")
+
+        // One of the updates will fail
+        `when`(source.fetchChapterList(favManga[0])).thenReturn(Observable.just(chapters))
+        `when`(source.fetchChapterList(favManga[1])).thenReturn(Observable.error<List<Chapter>>(Exception()))
+        `when`(source.fetchChapterList(favManga[2])).thenReturn(Observable.just(chapters3))
+
+        service.updateMangaList(service.getMangaToUpdate(null)).subscribe()
+
+        // There are 3 network attempts and 2 insertions (1 request failed)
+        assertThat(service.db.getChapters(favManga[0]).executeAsBlocking()).hasSize(2)
+        assertThat(service.db.getChapters(favManga[1]).executeAsBlocking()).hasSize(0)
+        assertThat(service.db.getChapters(favManga[2]).executeAsBlocking()).hasSize(2)
+    }
+
+    private fun createChapters(vararg urls: String): List<Chapter> {
+        val list = ArrayList<Chapter>()
+        for (url in urls) {
+            val c = Chapter.create()
+            c.url = url
+            c.name = url.substring(1)
+            list.add(c)
+        }
+        return list
+    }
+
+    private fun createManga(vararg urls: String): List<Manga> {
+        val list = ArrayList<Manga>()
+        for (url in urls) {
+            val m = Manga.create(url)
+            m.title = url.substring(1)
+            m.favorite = true
+            list.add(m)
+        }
+        return list
+    }
+}

+ 0 - 18
app/src/test/java/eu/kanade/tachiyomi/injection/module/TestDataModule.kt

@@ -1,18 +0,0 @@
-package eu.kanade.tachiyomi.injection.module
-
-import android.app.Application
-import eu.kanade.tachiyomi.data.network.NetworkHelper
-import eu.kanade.tachiyomi.data.source.SourceManager
-import org.mockito.Mockito
-
-class TestDataModule : DataModule() {
-
-    override fun provideNetworkHelper(app: Application): NetworkHelper {
-        return Mockito.mock(NetworkHelper::class.java)
-    }
-
-    override fun provideSourceManager(app: Application): SourceManager {
-        return Mockito.mock(SourceManager::class.java, Mockito.RETURNS_DEEP_STUBS)
-    }
-
-}