单元测试的使用以及Vue3-Element Plus入门
一、单元测试Unit Test
一般用来测试业务层
关于使用:引入依赖"
<!-- 单元测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
业务测试的类名必须以Tests
结尾且类名上面加上注解:@SpringBootTest
package com.stedu;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stedu.model.Member;
import com.stedu.model.search.MemberSearchBean;
import com.stedu.service.MemberService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;@SpringBootTest
class Crm2026ApplicationTests {@Autowired//依赖注入:字段注入private MemberService memberService;//单元测试 :@DisplayName("单元测试hello")//单元测试名字,方便用户体验的@Testpublic void testHello(){Integer a = 10;//测试断言:断言通过则单元测试通过 ,断言不通过则单元测试不通过//使用工具类:AssertionsAssertions.assertEquals(20,a);//不通过,期待的是20,但是实际是10;}@DisplayName("测试获取所有会员")@Testpublic void testAll(){//单元测试不能有参数Page<Member> page = new Page<>(1,5);MemberSearchBean msb = new MemberSearchBean();msb.setName("晓");page = this.memberService.findAll(page,msb);Long total = page.getTotal();//总数Assertions.assertEquals(4,total);List<Member> members = page.getRecords();//获取所有查询记录}}
二 、Vue—Element Plus
官网
1.安装Element Plus :
pnpm install element-plus
2.安装图标库 :
安装Element Plus图标库:
https://element-plus.org/zh-CN/component/icon.html
pnpm install @element-plus/icons-vue
安装后验证 :
3.安装之后进行配置
导入相关库:
import ElementPlus from 'element-plus'//引入element-plus主程序库
import 'element-plus/dist/index.css'//引入css文件
import zhCn from 'element-plus/es/locale/lang/zh-cn'//导入中文本地化
import * as ElementPlusIconsVue from '@element-plus/icons-vue'//引入所有的图标库
//设置使用Element-plus:注意位置
app.use(ElementPlus, {locale: zhCn,
})
4.正式使用Element-plus写前端示例:
需要写的内容写在<template></template>
标签中
书写顺序 :(1)先写表单/表格等页面展示部分
(2)然后根据事件需要先创建对象
(3)绑定事件:比如性别:当选中女的时候是 真正的选中,(1)其实是只有页面的展示的部分 ,还不能具体的真正选中数据或者实现真正操作 需要 :data 属性
表格
比如我们在页面展示表格:
(1)html部分展示表格 :框架
(2)加上属性真正展示:实现真正的展示要加上 属性:data
必须加上:
冒号开头的属性值是变量。这个变量必须在js里面有
<!-- 表格区 --><div class="grid"><el-table :data="members" stripe border class="data-grid"><el-table-column prop="id" label="ID" width="80"/><el-table-column prop="phone" label="手机号" width="150"/><el-table-column prop="name" label="姓名" width="150"/><el-table-column prop="pinyin" label="拼音" width="180"/><el-table-column prop="sex" label="性别" width="60"/><el-table-column prop="birthday" label="出生日期" width="150"/><el-table-column prop="email" label="邮箱" width="240"/><el-table-column prop="wechat" label="微信号" width="240"/><el-table-column prop="description" label="备注" show-overflow-tooltip/></el-table></div>
(3)创建响应式对象: JS里面,改变对象的值,页面会重新渲染。数据的变化驱动页面重新刷新
<script setup>
import {onMounted, ref, reactive} from "vue"
import api from "@/util/api";
import {CirclePlus, Delete, Edit, Refresh, Search} from "@element-plus/icons-vue";///////////////////////////////////
let members = ref();//创建一个响应式对象
//查询全部会员
async function search(pageNo = 1, pageSize = 10) {let resp = await api({url: "/members",method: "get",params: {pageNo,pageSize}});//console.log(resp);members.value = resp.data.records;//会员数据
}
//当组件挂载完毕之后触发
onMounted(() => {search();
});
</script>
按钮:
思路:先从官网加上 首先最基础的展示,然后添加修饰(按钮的修饰官网 提供的很全面)最后 绑定事件 :添加函数:自己写函数
<!-- 按钮区--><div class="action"><!-- 通过查看官网 ,设置type的属性primary就是让按钮背景颜色变成蓝色,:icon就是根据官网给他设置图标,然后@click=""是点击事件绑定,触发对应的方法关于@click=""中的():需要事件对象时省略括号,需要传参时加括号。--><el-button type="primary" :icon="CirclePlus" @click="add">新增</el-button><el-button type="primary" :icon="Edit">修改</el-button><el-button type="primary" :icon="Search" @click="search()">查询</el-button><el-button type="primary" :icon="Refresh" @click="reset">重置</el-button><el-button type="danger" :icon="Delete" @click="remove">删除</el-button></div>
但是还无法点击,绑定事件,添加对应的函数:也就是@click=""
是点击事件绑定,触发对应的方法部分即可 。
分页条 :
模板 :
<el-paginationv-model:current-page="绑定数据模型里面的页码 "v-model:page-size="绑定数据模型里面的页面大小":page-sizes="[100, 200, 300, 400]"layout="total, sizes, prev, pager, next, jumper":total="绑定数据模型里面的总页数"/>
示例:
<!-- 分页条 --><div class="pagination"><el-paginationv-model:current-page="memberPi.pageNo"v-model:page-size="memberPi.pageSize":page-sizes="[10, 20, 30, 50, 100]"layout="total, sizes, prev, pager, next, jumper":total="memberPi.total"class="member-pi"background@change="memberPiChange"/></div>
上面对应的数据模型:
//会员数据分页
let memberPi = reactive({pageNo: 1,pageSize: 10,total: 0
});
具体赋值及其他操作
全部js代码部分
<script setup>
import {onMounted, ref, reactive} from "vue"
import api from "@/util/api";
import {CirclePlus, Delete, Edit, Refresh, Search} from "@element-plus/icons-vue";///////////////////////////////////
let members = ref();//创建一个响应式对象//查询全部会员
async function search(pageNo = 1, pageSize = 10) {let resp = await api({url: "/members",method: "get",params: {pageNo,pageSize}});//console.log(resp);members.value = resp.data.records;//会员数据memberPi.pageNo = resp.data.current;memberPi.pageSize = resp.data.size;memberPi.total = resp.data.total;
}//当页码或页面大小改变时触发
function memberPiChange(pageNo, pageSize) {//console.log(pageNo, pageSize);search(pageNo, pageSize);
}//当组件挂载完毕之后触发
onMounted(() => {search();
});
</script>
查询区域
<!-- 查询区 --><div class="search"><el-form inline :model="memberSearchModel" ref="memberSearchForm"><el-form-item label="ID:" prop="id"><el-input v-model="memberSearchModel.id" placeholder="请输入会员ID"/></el-form-item><el-form-item label="姓名:" prop="name"><el-input v-model="memberSearchModel.name" placeholder="请输入会员姓名"/></el-form-item><el-form-item label="性别:" prop="sex"><el-select v-model="memberSearchModel.sex" :empty-values="[null]" style="width: 200px"><el-option label="不限" value=""/><el-option label="男" value="男"/><el-option label="女" value="女"/></el-select></el-form-item><el-form-item label="出生日期:" prop="birthdayRange"><el-date-pickertype="daterange"range-separator="~"start-placeholder="日期从"end-placeholder="日期止"v-model="memberSearchModel.birthdayRange"value-format="YYYY-MM-DD"/></el-form-item><el-form-item label="手机号:" prop="phone"><el-input v-model="memberSearchModel.phone" placeholder="请输入会员手机号"/></el-form-item></el-form></div>
5.删除操作的实现(后端)
servcie层方法
package com.study.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.model.Member;
import com.study.model.search.MemberSearchBean;
import java.util.List;public interface MemberService {//查询全部客户Page<Member> findAll(Page<Member> page, MemberSearchBean msb);//删除操作:批量删除(多个--传集合:是客户Id也就是整型),返回受影响的行数int delete(List<Integer> ids);
}
package com.study.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.model.Member;
import com.study.model.search.MemberSearchBean;
import java.util.List;public interface MemberService {//查询全部客户Page<Member> findAll(Page<Member> page, MemberSearchBean msb);//删除操作:批量删除(多个--传集合:是客户Id也就是整型),返回受影响的行数int delete(List<Integer> ids);
}
根据Id删除mybatis-plus底层已经提供了,直接调方法就行,所以不用写mapper层了
Controller层:
package com.study.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.model.Member;
import com.study.model.search.MemberSearchBean;
import com.study.service.MemberService;
import com.study.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;import java.util.List;@RestController
@RequestMapping("api/v1/members" )//接收前端的请求,路径与前端发送请求的路径一致
public class MemberController {private MemberService memberService;@Autowired//依赖注入:创建对象:public void setMemberService(MemberService memberService) {this.memberService = memberService;}//查询全部客户:@GetMappingpublic ResponseEntity<JsonResult<?>> findAll(@RequestParam(defaultValue = "1") Integer pageNo,@RequestParam(defaultValue = "15") Integer pageSize,MemberSearchBean msb){Page<Member> page = new Page<>(pageNo,pageSize);Page<Member> all = memberService.findAll(page, msb);return ResponseEntity.ok(JsonResult.success(all));}@DeleteMapping//删除操作public ResponseEntity<JsonResult<?>> delete(@RequestBody Integer[] ids){int count = memberService.delete(List.of(ids));if(count==0){return ResponseEntity.ok(JsonResult.fail("删除会员失败"));}else {return ResponseEntity.ok(JsonResult.success(count));}}
}
Service层:
package com.study.service;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.model.Member;
import com.study.model.search.MemberSearchBean;
import java.util.List;public interface MemberService {//查询全部客户Page<Member> findAll(Page<Member> page, MemberSearchBean msb);//删除操作:批量删除(多个--传集合:是客户Id也就是整型),返回受影响的行数int delete(List<Integer> ids);
}
package com.study.service.impl;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.study.mapper.MemberMapper;
import com.study.model.Member;
import com.study.model.search.MemberSearchBean;
import com.study.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;@Service//控制反转:创建对象
public class MemberServiceImpl implements MemberService {@Autowiredprivate MemberMapper memberMapper;@Overridepublic Page<Member> findAll(Page<Member> page, MemberSearchBean msb) {return memberMapper.findAll(page,msb);}@Overridepublic int delete(List<Integer> ids) {return memberMapper.deleteByIds(ids);//注意选对方法}}
其他具体操作可以参考真正的项目实战博客。