跳转至

apps\store\src\test\java\cn\nfarms\store\OrderKeysTest.kt

源码路径:apps\store\src\test\java\cn\nfarms\store\OrderKeysTest.kt · 76 行

package cn.nfarms.store

import cn.nfarms.store.data.OrderLine
import cn.nfarms.store.data.OrderKeys
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Test

/**
 * 幂等键的派生规则。
 *
 * 这个键是「不重复记账」的唯一依据,所以它的每条性质都要有测试钉住 ——
 * 键一变,后端就会把重试当成新单。
 */
class OrderKeysTest {

    private fun line(id: String, qty: Int, unit: Int, opt: String? = null) =
        OrderLine(itemId = id, name = id, optionName = opt, unitFen = unit, qty = qty)

    @Test
    fun same_inputs_same_key() {
        val lines = listOf(line("a", 1, 1800), line("b", 2, 1200))
        val k1 = OrderKeys.of("shop", 1_697_000_000_000, lines)
        val k2 = OrderKeys.of("shop", 1_697_000_000_000, lines)
        assertEquals("同样一次下单必须得到同样的键", k1, k2)
    }

    /**
     * 行项目顺序不影响键 —— 购物车的加入顺序不该改变订单身份。
     *
     * 这条是 `OrderKeys.of` 里 `sortedWith` 的护栏:去掉排序这条就红。
     */
    @Test
    fun line_order_does_not_change_key() {
        val a = listOf(line("a", 1, 1800), line("b", 2, 1200))
        val b = listOf(line("b", 2, 1200), line("a", 1, 1800))
        assertEquals(OrderKeys.of("shop", 1, a), OrderKeys.of("shop", 1, b))
    }

    @Test
    fun different_time_different_key() {
        val lines = listOf(line("a", 1, 1800))
        assertNotEquals(
            OrderKeys.of("shop", 1_000, lines),
            OrderKeys.of("shop", 1_001, lines),
        )
    }

    @Test
    fun different_quantity_or_price_different_key() {
        assertNotEquals(
            OrderKeys.of("shop", 1, listOf(line("a", 1, 1800))),
            OrderKeys.of("shop", 1, listOf(line("a", 2, 1800))),
        )
        assertNotEquals(
            OrderKeys.of("shop", 1, listOf(line("a", 1, 1800))),
            OrderKeys.of("shop", 1, listOf(line("a", 1, 1900))),
        )
    }

    @Test
    fun different_shop_different_key() {
        val lines = listOf(line("a", 1, 1800))
        assertNotEquals(OrderKeys.of("s1", 1, lines), OrderKeys.of("s2", 1, lines))
    }

    /** 规格不同就是不同的商品(热美式 ≠ 冰美式)。 */
    @Test
    fun option_is_part_of_identity() {
        assertNotEquals(
            OrderKeys.of("shop", 1, listOf(line("americano", 1, 1800, "hot"))),
            OrderKeys.of("shop", 1, listOf(line("americano", 1, 2000, "ice"))),
        )
    }
}