这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战
小试牛刀
经过漫长的准备,我们终于可以开始了!还记得TDD(测试驱动开发)吗?先写测试,后写实现。所以我们先在「RoomTest.kt」文件中添加测试插入歌曲的测试案例。
@Test
fun testInsertSongs() {
val songs = List<Song>(10) {
Song( songName = "夜曲", singer = "周杰伦")
}
dao.addSongs(songs)
assertEquals(10, dao.findSongCount())
}
我们先实例化一个包含10个Song对象的列表,然后用我们将要写的增加数据的函数,将10个歌曲数据加入表中,之后我们需要验证新增数据的函数的有效性,就以查看表长度是否符合预期为判定条件。
我们还需要在「TestDao.kt」中声明一下addSongs和findSongCount。
@Insert
fun addSongs(list: List<Song>)
@Query("SELECT COUNT(*) FROM Song")
fun findSongCount(): Int
那现在执行一下测试看看结果吧,应该通过的。
Room注释
你可能会觉得这有些奇怪,为什么只需要在「TestDao」接口的声明的抽象方法就能实现功能了呢?
实际上,像 @Insert(增加注释)、@Query(查询注释)这些注释是Room提供的,而使用这些注释的抽象方法后Room会帮你生成一个实现。
数据库的增删改查,Room都对应的注释:
- @Insert 增
- @Delete 删
- @Update 改
- @Query 查 此外还有个原子性注释:@Transaction
增删改的注释使用方法几乎一致,参数是可以是单个元素、多个元素或者是一个列表。返回的可能是变更的行数或者是行数列表。不过有了测试环境,我们可以用一个很低的成本去验证api的结果。(官方的文档也可能有错误和不完备的地方,或者一些进阶的用法,例如:类型转换器或者Fts4)
按照官方文档所述,@Insert会根据不同参数类型返回变更的单个行数或者行数集合,而且这个行数是long类型的,所以我们按照返回类型准备了四个测试案例,返回值类型为:Int、List<Int>、Long、List<Long>。我们现在测试中添加这一段。(注意,测试文件中的@Before和@After不需要动,之后也是一样,不在赘述)
@Test
fun testInsert1() {
val song = Song( songName = "夜曲", singer = "周杰伦")
assertEquals(1, dao.addSongs1(song))
}
@Test
fun testInsert2() {
val song = listOf(Song( songName = "夜曲", singer = "周杰伦"))
assertEquals(listOf(1), dao.addSongs2(song))
}
@Test
fun testInsert3() {
val song = Song( songName = "夜曲", singer = "周杰伦")
assertEquals(1L, dao.addSongs3(song))
}
@Test
fun testInsert4() {
val song = listOf(Song( songName = "夜曲", singer = "周杰伦"))
assertEquals(listOf(1L), dao.addSongs4(song))
}
加下来,我们在TestDao.kt中加入实现。
@Insert
fun addSongs1(song:Song):Int
@Insert
fun addSongs2(list: List<Song>):List<Int>
@Insert
fun addSongs3(song:Song):Long
@Insert
fun addSongs4(list: List<Song>):List<Long>
点击一下run,你发现这次测试甚至编译都没过去,AS会警告你「Not sure how to handle insert method's return type.无法处理你@Insert方法的返回值。」
Room的编译器检查覆盖面很广,这样也能让你尽早发现你代码的漏洞。好吧,那就删掉测试1和测试2以及它们的实现吧。再跑一下测试,就能看到成功的结果了。
增删改这三项大体相同,有兴趣的同学可以自己实验一下,之后的一篇我会开始不一样的@Query。