[Day 16] 第一个和资料库互动的测试

知道什麽是自动测试之後,我们来看看怎麽进行和资料库互动的自动测试。

测试目标

假设我们现有的资料关联有 usertag 的多对多关联

object Users : IntIdTable() {  
    val name = varchar("name", 50)  
}  
  
object Tags : IntIdTable() {  
    val name = varchar("name", 50)  
}  
  
object UsersTags : IntIdTable() {  
    val user = reference("user", Users)  
    val tag = reference("tag", Tags)  
}  
  
class Tag(id: EntityID<Int>) : IntEntity(id) {  
    companion object : IntEntityClass<Tag>(Tags)  
    var name by Tags.name  
 	var users by User via UsersTags  
}  
  
class User(id: EntityID<Int>) : IntEntity(id) {  
    companion object : IntEntityClass<User>(Users)  
    var name by Users.name  
 	var tags by Tag via UsersTags  
}

并且连接 MySQL 的资料库

fun main() {  
    Database.connect(  
		"jdbc:mysql://localhost:3306/exposedyoutubedemo?useSSL=false",  
		driver = "com.mysql.jdbc.Driver",  
		user = "user",  
		password = "password"  
	)
	// 其他函数写在後面
}

我们今天测试的程序,是一个用来写入 usertag 的函数,我们一开始写法是这样

fun userAddTag(user: User, tag: Tag) {  
  	// user 多加一个新的 tag
  	transaction {  
 		user.tags = SizedCollection(listOf(tag))  
	}
}

接着,我们来测试一下这段程序吧!

切换资料库

在自动测试阶段,很重要的一个事项,是不能更动到正式的资料库。毕竟我们不会希望有人不小心在正式环境运行了测试程序,就导致正式资料全部被搞乱了。

那麽,要怎麽在测试阶段和正式阶段所串连的资料库不一样呢?

利用我们 Day 14 的文章内容,我们可以将原本程序稍微调整,让连线改成用测试环境的资料库进行测试。

假设我们希望改成利用 H2 in memory 的资料库进行测试,跟上次类似,我们在 tests/kotlin/ 资料夹内,建立一个 UserAddTagKtTest.kt 档案,来测试这个函数。


internal class UserAddTagKtTest {
	fun `测试全新用户加上标签`() {
	Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;", driver = "org.h2.Driver")  
	    transaction {
			SchemaUtils.create(Users)  
			SchemaUtils.create(Tags)  
			SchemaUtils.create(UsersTags)  
			val testUser = User.new {  
				name = "TestUser"  
			}  
			val testTag = Tag.new {  
				name = "TestTag"  
			}  
			userAddTag(testUser, testTag)  
			assertEquals(
				listOf(testTag),
				testUser.tags.toList()
			)  
		}  
	}
}

运作测试之後,如果顺利的话,我们会得到绿灯。

这样我们第一阶段的测试就完成了!

重复写入 Tag

接着,我们想到一个新的状况:如果一个 user 写入多个 tag,那麽还会成功吗?

我们用类似的逻辑,再写一个测试案例

@Test  
fun `测试用户加上多个标签`() {  
Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;", driver = "org.h2.Driver")  
    transaction {  
 		SchemaUtils.create(Users)  
        SchemaUtils.create(Tags)  
        SchemaUtils.create(UsersTags)  
        val testUser = User.new {  
 			name = "TestUser"  
 		}  
		val testTag = Tag.new {  
			name = "TestTag"  
		}  
		val testTag2 = Tag.new {  
			name = "TestTag2"  
		}  
		userAddTag(testUser, testTag)  
		userAddTag(testUser, testTag2)  
		assertEquals(
			listOf(testTag, testTag2),
			testUser.tags.toList()
		)  
    }

跟前面的逻辑是几乎一样的,只是我们多加了一个 testTag2

这时候如果我们运作测试,会出现类似这样的错误

expected:<[Tag@530069b7, Tag@3714e9e4]> but was:<[Tag@3714e9e4]>
Expected :[Tag@530069b7, Tag@3714e9e4]
Actual   :[Tag@3714e9e4]

这是为什麽呢?回到我们的程序检查,原来我们一开始的程序写错了!只会拿新的 Tag 覆盖掉所有 useruser.tags

所以我们重新调整一下 userAddTag 函数

fun userAddTag(user: User, tag: Tag) {
    transaction {
     user.tags = SizedCollection(
         user.tags.toList() 
         + listOf(tag)
     )
    }
}

重新运作一次测试,我们就会发现两个测试都通过了!


<<:  Day6 React搭配JSX运用

>>:  [Day 10] 第一主餐 pt.3-Djgnao与网页间的连结

Day 21网路通讯协定

前言 网路通讯协定就是为电脑进行资料交换而建立的规章或标准的集合。常用的有TCP/IP协定、HTTP...

[Day27] Flutter with GetX connectivity

connectivity侦测网路状态 判断当前是Wifi或是一般手机网路 在connectivity...

[Day28] React - 建立React 元件 (Component )

前面介绍了如何用JSX语法建立React元素,接着这篇会记录如何建立React元件,即前面提到的Re...

CMoney软件工程师战斗营_Week 13

由於疫情的关系 大家已在家学习一个月 原本想说最要克服的是自制力 但没想到事情多到 我也没时间发闲~...

Know all about types of research papers in Australia

Know all about types of research papers in Austral...