Laravel 单元测试实战(2)- 编写实际功能并让代码测试通过

Laravel框架
369
0
0
2022-11-15

Laravel 单元测试实战(2)- 编写实际功能并让代码测试通过

github 项目地址

git clone https://gitee.com/three_kingdoms_of_zhang/unit_test_practice.git
composer install
git checkout v2.0

代码是完整的,包括迁移,模型类,和全部功能。

service 实际编写,完成功能。

class ServiceOrder
{

    /**
     * 根据购物车信息,和已有的优惠券,查找最优惠的一张优惠券。
     *
     * @param array $shopping_cart 前端传来的商品信息。
     * // 购物车格式
     * $shopping_cart = [
     *            [
     *                'goods_id' => 1,
     *                'count' => 3,
     *            ],
     *            [
     *                'goods_id' => 2,
     *                'count' => 1,
     *            ],
     *            [
     *                'goods_id' => 3,
     *                'count' => 2,
     *            ],
     *        ];
     *
     * @param Collection $goods_records 自己查的数据库信息,商品的。
     * @param Collection $user_coupon_records 自己查的用户优惠券信息。
     *
     * @return [
     *    'saved_money' => 0, //优惠券自身的等价金额
     *    'user_coupon_record' => [ //优惠券记录,或者null
     *        'id' => 4,
     *        'type' => 2,
     *        'coupon_value' => 0.9,
     *        'condition_money' => 50,
     *    ]
     * ]
     */
    public function find_user_coupon_from_shopping_cart(array $shopping_cart,Collection $goods_records,
                                                        Collection $user_coupon_records):array
    {
        $total = $this->calculate_total_price( $shopping_cart, $goods_records );
        $finded_user_coupon = $user_coupon_records
            ->filter(function ($user_coupon)use($total){ // 先根据总价过滤一部分
                return $user_coupon['condition_money'] < $total;
            })->map(function($user_coupon)use($total){ //开始计算节省金额
                if ($user_coupon['type']==1) {
                    $user_coupon['saved_money'] = $user_coupon['coupon_value'] ;
                }
                if ($user_coupon['type']==2) {
                    $user_coupon['saved_money'] = $total * (1- $user_coupon['coupon_value']) ;
                }
                return $user_coupon;
            })->sortByDesc(function ($user_coupon) { //根据节省金额倒序排
                return $user_coupon['saved_money'];
            })->first();                             //取出第一个优惠券。
        if ($finded_user_coupon) {
            return [
                 'saved_money' => $finded_user_coupon['saved_money'], //优惠券自身的等价金额
                 'user_coupon_record' => [ //这个对应表中的一条记录。
                     'id' => $finded_user_coupon['id'],
                     'type' => $finded_user_coupon['type'],
                     'coupon_value' => $finded_user_coupon['coupon_value'],
                     'coupon_name' => $finded_user_coupon['coupon_name'],
                 ]
              ];
        }
        return [
            'saved_money' => 0,
            'user_coupon_record' => null,
        ];
    }

    // 算总价
    private function calculate_total_price(array $shopping_cart,Collection $goods_records):float
    {
        $total=0;
        foreach( $shopping_cart as $shop_count){
            $count = $shop_count['count'];
            $unit_price=0;
            foreach ( $goods_records as $goods ){
                if ( $goods['id'] == $shop_count['goods_id'] ){
                    $unit_price = $goods['price'];
                    break;
                }
            }
            if (!$unit_price) {
                throw new \Exception('参数错误');
            }
            $total += $count * $unit_price;
        }
        return $total;
    }



}

同时,发现了原先的单元测试代码要改一句话。断言节省金额的代码。

原先,
$this->assertEquals($result['saved_money'], $result_expect['saved_money']);

应改成:
$this->assertEqualsWithDelta($result['saved_money'], $result_expect['saved_money'],0.02);

执行单元测试

./vendor/bin/phpunit ./tests/Unit/ServiceOrderTest.php

会显示测试通过。

总结:

把功能实际写好,然后再次运行单元测试代码,这次通过了。

同时发现,单元测试必须修改,因为涉及到小数运算,无法精确,所以需要忽略一定的精度。

实际上,这接口就已经完成了。

但是,后面再写一个集成测试。带上数据库,彻底验证该代码的正确性。

另外,这里写的单元测试,覆盖的逻辑比较少,还需要测试边界条件,比如优惠券列表为空等情况。