其实在程序考试结束後,连接着两人关系的补课也该跟着结束了。
但是诗忆彷佛没注意到这点似的,带着早就准备好的甜食等在门口,看到最後一个考生离开马上跑进教室。
「学姐!」
「嗯?」唯心本来正在擦拭白板,听到声音便偏过头来看。
「学姐也累了吧?我这里有饼乾和糖果唷。」
「系计中教室里禁止饮食唷。」
「啊,不小心忘记了,那,等学姐出来再一起吃吧。」诗忆把食物收回包里。
「好唷,我快收拾完了,对了,我听说你对MockK有兴趣?」
「咦?学姐怎麽知道的?」
「当然是有人告诉我的呀。」唯心看了一下旁边开着的电脑。「要不然我们先稍微研究一下再吃东西吧。」
打开MockK官网的网址和IDE,唯心注意到有版本搭配的说明。
「From version 1.10.0 MockK does not support Kotlin 1.2.*
,所以先检查一下我们现在使用的kotlin版本吧。」於是乘载函式库资讯的build.gradle.kts再次受到关注。
plugins {
kotlin("jvm") version "1.5.10"
}
「是1.5.10。」诗忆说。
「对呀,那我们就可以安心使用1.10.0後的最新版本了。」唯心说着,就把函式库连着变数直接黏贴上去。
dependencies {
//...
testImplementation("io.mockk:mockk:{version}")
}
「学姐,稍等一下,我记得最新版本号在官网上面。」诗忆想要先离开IDE画面。
「啊,不用那麽麻烦,来,我教你用IDE拿最新版本的方法。」唯心点击IDE下方的Dependencies。
打开了函式库管理列表,点击MockK的那列,选了版本表最上方的1.12.0。
build.gradle.kts里的函式库的版本号变数也自动替换上被选择的版本。
dependencies {
//...
testImplementation("io.mockk:mockk:1.12.0")
}
「好了,那我们来看看官网的范例吧,毕竟这麽多函式不可能每个都试一遍呀。」唯心笑笑。
val car = mockk<Car>()
every { car.drive(Direction.NORTH) } returns Outcome.OK
car.drive(Direction.NORTH) // returns OK
verify { car.drive(Direction.NORTH) }
confirmVerified(car)
她看完范例後,很快就有了思路。「我觉得我们可以继续用之前的饮料例子唷。」
class Drink(val name: String, val price: Int) {//饮料类别
fun freeAdd(): Boolean {//是否免费加料
return true
}
}
class DrinkOrder(private val drink: Drink) {//饮料订单类别
var price = drink.price
fun add() {//加料
if (!drink.freeAdd()) {
price += 10
}
}
}
准备好饮料类别和饮料订单类别後,唯心着手写新测试。
import io.mockk.*
import kotlin.test.Test
import kotlin.test.assertEquals
class DrinkOrderTest {
@Test
fun add() {
val drink = mockk<Drink>()
every { drink.price } returns 60
every { drink.freeAdd() } returns false
val order = DrinkOrder(drink)
}
}
「咦?所以我们不用真的写一个Drink物件,本来还在想饮料订单类别不需要饮料名字,还要想饮料名字有点麻烦的。」诗忆睁大眼睛。
「是呀,因为饮料订单依赖着外部传入的饮料物件,所以要用mockk<T>(...)
的泛型概念建立饮料的假物件,不是本尊唷。接着用every
假造必要的函式和变数的回传,就可以在饮料订单里帮饮料加料了。针对外部物件的假造,我记得是用Stub
来称呼,但测试的主角是饮料订单呢,所以接下来要验证饮料订单加料的结果。」
@Test
fun add() {
val drink = mockk<Drink>()
every { drink.price } returns 60
every { drink.freeAdd() } returns false
val order = DrinkOrder(drink)
order.add()
verify{ drink.freeAdd() }
assertEquals(60, order.price)
}
「为什麽要verify
函式drink.freeAdd()
呢?」
「喔,是为了确定前面的执行过程中有没有呼叫到这个函式呀,因为order.add()
的前提条件需要drink.freeAdd()
。顺带一提,every
的位置很重要唷,如果你没提供饮料资料就投进饮料订单,会出现错误唷。」
class DrinkOrderTest {
@Test
fun add() {
val drink = mockk<Drink>()
val order = DrinkOrder(drink)
every { drink.price } returns 60
every { drink.freeAdd() } returns false
}
}
出现错误no answer found for: Drink(#1).getPrice()
。因为DrinkOrder初始化所要取得drink.price
的值就是呼叫drink.getPrice()
。
class DrinkOrderTest {
@Test
fun add() {
val drink = mockk<Drink>()
every { drink.price } returns 60
val order = DrinkOrder(drink)
every { drink.freeAdd() } returns false
order.add()
verify{ drink.freeAdd() }
assertEquals(60, order.price)
}
}
「学姐,范例里还有confirmVerified
,你没加进去呢。」
「嗯⋯⋯其实那是用来确认是不是验证过所有的函式,没验证的会出现在Not verified calls
清单里。顺带一提,只能验证mock的对象,也就是说,我们只能confirmVerified(drink),不能confirmVerified(order),後者会出现错误can't find stub DrinkOrder@137ceb57
。」
「学姐,既然范例都说完了,我们可以去吃点心了吧。」诗忆觉得她的大脑和肠胃正在一同发出抗议。
「喔,差点都忘记这回事了呢,我们走吧。」唯心转身提起包,却没留意到旁边有个被留在桌上的水杯。
杯里的水,洒了出来。
急忙伸出手试图阻止水往电脑溅的诗忆,突然脑海中有什麽闪过,感觉眼前的场景好像在以前也发生过。
注:发文日和截图的日期不一定是同一天,所以价格计算上和当日不同,是很正常的。 声明:这一系列文章并无...
接下来我们来谈谈 MVP ( Model-View-Presenter ),在知道 MVC 也只是在...
今天铁人赛的倒数第一天了 ^^,要和大家分享的是,如何接收永丰银行丰收款金流平台收到顾客的银行转帐汇...
有哪些文件:orientation. 技术、API、测试等 自动化产生,自动化建置流程的一部分 新...
今天要进入程序码的部分了。 我会以JavaScript(JS)为基础做比较与解释, 同时也了解两者在...