I'm learning how to use the room framework, but I can't update or delete entity in androidTest. Here is my code:
@Database(entities = [Note::class], version = 1)
@TypeConverters(com.misaka.workflow.data.local.TypeConverter::class)
abstract class SQLiteDataBase : RoomDatabase() {
abstract fun getNoteDAO(): NoteDAO
companion object {
@Volatile
private var INSTANCE: SQLiteDataBase? = null
fun getInstance (context: Context): SQLiteDataBase {
return INSTANCE ?: synchronized(this) {
INSTANCE ?: Room.databaseBuilder(
context.applicationContext,
SQLiteDataBase::class.java,
"WorkFlow"
).build().also { INSTANCE = it }
}
}
}
}
@Dao
interface NoteDAO {
@Query("select * from note")
fun getAllNote(): List<Note>
@Delete
fun deleteNotes(vararg notes: Note): Int
@Insert
fun insertNewNotes(vararg node: Note)
@Update(onConflict = OnConflictStrategy.REPLACE)
fun updateNote(note: Note): Int
@Query("select * from note")
fun getAllNoteInFlow(): Flow<List<Note>>
@Query("delete from note where id = :id")
fun test(id: Int)
@Query("update note set title = :title where id = :id")
fun test2(id: Int, title: String)
}
@Entity(
tableName = "note"
)
data class Note(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
@ColumnInfo(name = "title")
val title: String = "",
@ColumnInfo(name = "noteContent")
val content: String = "",
@ColumnInfo(name = "modifyTime")
val modifyTime: LocalDateTime = LocalDateTime.now()
)
class NoteUnitTest {
private lateinit var repository: NoteRepository
private lateinit var database: SQLiteDataBase
private lateinit var dao: NoteDAO
@Before
fun setup() {
database = Room.inMemoryDatabaseBuilder(
ApplicationProvider.getApplicationContext(),
SQLiteDataBase::class.java
).build()
dao = database.getNoteDAO()
repository = NoteRepository(dao)
}
@After
fun close() {
database.close()
}
@Test
fun testDAO() = runTest {
try {
val noteFlow = dao.getAllNoteInFlow()
val note = Note(title = "test", content = "testContent", modifyTime = LocalDateTime.now())
dao.insertNewNotes(note)
launch {
noteFlow.collect { value ->
println(value)
}
}
val newNote = note.copy(title = "test1", id = note.id)
dao.test2(newNote.id, newNote.title)
dao.updateNote(newNote)
dao.deleteNotes(newNote)
} catch (e: Exception) {
println(e.stackTrace)
}
}
}
After running the test, I only get one value from the Flow, which is the entity I inserted at the beginning. I don't understand what the problem is. I would be very grateful if anyone could help me.
You can't update/delete your entities because of the ids. You are declaring id like this val id: Int = 0
but ids in database starts with 1. Inserting Note instance will not update id of the instance. Id of note in your code is still 0 and when you are trying to update/delete them, database simply can't find them.
As mentioned here, you cant return Long
for single insert operation containing number of inserted row (id), so you can e.g. set Id value on insert like this:
Change id
from val
to var
and type from Int
to Long
:
@Entity(
tableName = "note"
)
data class Note(
@PrimaryKey(autoGenerate = true)
var id: Long = 0,
@ColumnInfo(name = "title")
val title: String = "",
@ColumnInfo(name = "noteContent")
val content: String = "",
)
Inside NoteDao
add insert for one note returning Long:
@Insert
fun insertNewNote(node: Note): Long
Then you can set note id while inserting it:
val note = Note(title = "test", content = "testContent")
note.id = dao.insertNewNote(note)
After these changes you will be able to update, delete notes and also see logs from noteFlow
collection.