目录
一个测试方法主要包括三部分
Junit 基本注解介绍
测试方法执行顺序
测试方法命名约定
基于 Spring 的单元测试编写
常用的 Mockito 方法
示例
一个测试方法主要包括三部分
1)setup
2)执行操作
3)验证结果
public class CalculatorTest {
Calculator mCalculator;
@Before // setup
public void setup() {
mCalculator = new Calculator();
}
@Test //assert 部分可以帮助我们验证一个结果
public void testAdd() throws Exception {
int sum = mCalculator.add(1, 2);
assertEquals(3, sum); //为了简洁,往往会static import Assert里面的所有方法。
}
@Test
@Ignore("not implemented yet") // 测试时忽略该方法
public void testMultiply() throws Exception {
}
// 表示验证这个测试方法将抛出 IllegalArgumentException 异常,若没抛出,则测试失败
@Test(expected = IllegalArgumentException.class)
public void test() {
mCalculator.divide(4, 0);
}
}
Junit 基本注解介绍
@BeforeClass
在所有测试方法执行前执行一次,一般在其中写上整体初始化的代码。
@AfterClass
在所有测试方法后执行一次,一般在其中写上销毁和释放资源的代码。
// 注意这两个都是静态方法
@BeforeClass
public static void test(){
}
@AfterClass
public static void test(){
}
@Before
在每个方法测试前执行,一般用来初始化方法(比如我们在测试别的方法时,类中与其他测试方法共享的值已经被改变,为了保证测试结果的有效性,我们会在@Before注解的方法中重置数据)
@After
在每个测试方法执行后,在方法执行完成后要做的事情。
@Test(timeout = 1000)
测试方法执行超过1000毫秒后算超时,测试将失败。
@Test(expected = Exception.class)
测试方法期望得到的异常类,如果方法执行没有抛出指定的异常,则测试失败。
@Ignore("not ready yet")
执行测试时将忽略掉此方法,如果用于修饰类,则忽略整个类。
@Test
编写一般测试用例用。
@RunWith
在 Junit 中有很多个 Runner,他们负责调用你的测试代码,每一个 Runner 都有各自的特殊功能,你根据需要选择不同的 Runner 来运行你的测试代码。
如果我们只是简单的做普通 Java 测试,不涉及 Spring Web 项目,你可以省略 @RunWith 注解,你要根据需要选择不同的 Runner 来运行你的测试代码。
测试方法执行顺序
按照设计,Junit不指定test方法的执行顺序。
@FixMethodOrder(MethodSorters.JVM)
:保留测试方法的执行顺序为JVM返回的顺序。每次测试的执行顺序有可能会所不同。
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
:根据测试方法的方法名排序,按照词典排序规则(ASC,从小到大,递增)。
Failure 是测试失败,Error 是程序出错。
测试方法命名约定
Maven本身并不是一个单元测试框架,它只是在构建执行到特定生命周期阶段的时候,通过插件来执行JUnit或者TestNG的测试用例。这个插件就是maven-surefire-plugin,也可以称为测试运行器(Test Runner),它能兼容JUnit 3、JUnit 4以及TestNG。
在默认情况下,maven-surefire-plugin的test目标会自动执行测试源码路径(默认为src/test/java/)下所有符合一组命名模式的测试类。这组模式为:
*/Test.java:任何子目录下所有命名以Test开关的Java类。
*/Test.java:任何子目录下所有命名以Test结尾的Java类。
*/TestCase.java:任何子目录下所有命名以TestCase结尾的Java类。
基于 Spring 的单元测试编写
首先我们项目一般都是 MVC 分层的,而单元测试主要是在 Dao 层和 Service 层上进行编写。从项目结构上来说,Service 层是依赖 Dao 层的,但是从单元测试角度,对某个 Service 进行单元的时候,他所有依赖的类都应该进行Mock。而 Dao 层单元测试就比较简单了,只依赖数据库中的数据。
Mockito
Mockito是mocking框架,它让你用简洁的API做测试。而且Mockito简单易学,它可读性强和验证语法简洁。
Mockito 是一个针对 Java 的单元测试模拟框架,它与 EasyMock 和 jMock 很相似,都是为了简化单元测试过程中测试上下文 ( 或者称之为测试驱动函数以及桩函数 ) 的搭建而开发的工具
相对于 EasyMock 和 jMock,Mockito 的优点是通过在执行后校验哪些函数已经被调用,消除了对期望行为(expectations)的需要。其它的 mocking 库需要在执行前记录期望行为(expectations),而这导致了丑陋的初始化代码。
SpringBoot 中的 pom.xml 文件需要添加的依赖:
org.springframework.boot
spring-boot-starter-test
test
进入 spring-boot-starter-test-2.1.3.RELEASE.pom 可以看到该依赖中已经有单元测试所需的大部分依赖,如:
若为其他 spring 项目,需要自己添加 Junit 和 mockito 项目。
常用的 Mockito 方法
方法名
描述
Mockito.mock(classToMock)
模拟对象
Mockito.verify(mock)
验证行为是否发生
Mockito.when(methodCall).thenReturn(value1).thenReturn(value2)
触发时第一次返回value1,第n次都返回value2
Mockito.doThrow(toBeThrown).when(mock).[method]
模拟抛出异常。
Mockito.mock(classToMock,defaultAnswer)
使用默认Answer模拟对象
Mockito.when(methodCall).thenReturn(value)
参数匹配
Mockito.doReturn(toBeReturned).when(mock).[method]
参数匹配(直接执行不判断)
Mockito.when(methodCall).thenAnswer(answer))
预期回调接口生成期望值
Mockito.doAnswer(answer).when(methodCall).[method]
预期回调接口生成期望值(直接执行不判断)
Mockito.spy(Object)
用spy监控真实对象,设置真实对象行为
Mockito.doNothing().when(mock).[method]
不做任何返回
Mockito.doCallRealMethod().when(mock).[method] //等价于Mockito.when(mock.[method]).thenCallRealMethod();
调用真实的方法
reset(mock)
重置mock
示例
验证行为是否发生
//模拟创建一个List对象
List mock = Mockito.mock(List.class);
//调用mock对象的方法
mock.add(1);
mock.clear();
//验证方法是否执行
Mockito.verify(mock).add(1);
Mockito.verify(mock).clear();
多次触发返回不同值
//mock一个Iterator类
Iterator iterator = mock(Iterator.class);
//预设当iterator调用next()时第一次返回hello,第n次都返回world
Mockito.when(iterator.next()).thenReturn("hello").thenReturn("world");
//使用mock的对象
String result = iterator.next() + " " + iterator.next() + " " + iterator.next();
//验证结果
Assert.assertEquals("hello world world",result);
模拟抛出异常
@Test(expected = IOException.class)//期望报IO异常
public void when_thenThrow() throws IOException{
OutputStream mock = Mockito.mock(OutputStream.class);
//预设当流关闭时抛出异常
Mockito.doThrow(new IOException()).when(mock).close();
mock.close();
}
使用默认Answer模拟对象
RETURNS_DEEP_STUBS 是创建mock对象时的备选参数之一
以下方法deepstubsTest和deepstubsTest2是等价的
@Test
public void deepstubsTest(){
A a=Mockito.mock(A.class,Mockito.RETURNS_DEEP_STUBS);
Mockito.when(a.getB().getName()).thenReturn("Beijing");
Assert.assertEquals("Beijing",a.getB().getName());
}
@Test
public void deepstubsTest2(){
A a=Mockito.mock(A.class);
B b=Mockito.mock(B.class);
Mockito.when(a.getB()).thenReturn(b);
Mockito.when(b.getName()).thenReturn("Beijing");
Assert.assertEquals("Beijing",a.getB().getName());
}
class A{
private B b;
public B getB(){
return b;
}
public void setB(B b){
this.b=b;
}
}
class B{
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getSex(Integer sex){
if(sex==1){
return "man";
}else{
return "woman";
}
}
}
参数匹配
@Test
public void with_arguments(){
B b = Mockito.mock(B.class);
//预设根据不同的参数返回不同的结果
Mockito.when(b.getSex(1)).thenReturn("男");
Mockito.when(b.getSex(2)).thenReturn("女");
Assert.assertEquals("男", b.getSex(1));
Assert.assertEquals("女", b.getSex(2));
//对于没有预设的情况会返回默认值
Assert.assertEquals(null, b.getSex(0));
}
class B{
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getSex(Integer sex){
if(sex==1){
return "man";
}else{
return "woman";
}
}
}
匹配任意参数
Mockito.anyInt()
任何 int 值 ;
Mockito.anyLong()
任何 long 值 ;
Mockito.anyString()
任何 String 值 ;
Mockito.any(XXX.class) 任何 XXX 类型的值 等等。
@Test
public void with_unspecified_arguments(){
List list = Mockito.mock(List.class);
//匹配任意参数
Mockito.when(list.get(Mockito.anyInt())).thenReturn(1);
Mockito.when(list.contains(Mockito.argThat(new IsValid()))).thenReturn(true);
Assert.assertEquals(1,list.get(1));
Assert.assertEquals(1,list.get(999));
Assert.assertTrue(list.contains(1));
Assert.assertTrue(!list.contains(3));
}
class IsValid extends ArgumentMatcher{
@Override
public boolean matches(Object obj) {
return obj.equals(1) || obj.equals(2);
}
}
注意:使用了参数匹配,那么所有的参数都必须通过matchers来匹配
Mockito继承Matchers,anyInt()等均为Matchers方法
当传入两个参数,其中一个参数采用任意参数时,指定参数需要matchers来对比
Comparator comparator = mock(Comparator.class);
comparator.compare("nihao","hello");
//如果你使用了参数匹配,那么所有的参数都必须通过matchers来匹配
Mockito.verify(comparator).compare(Mockito.anyString(),Mockito.eq("hello"));
//下面的为无效的参数匹配使用
//verify(comparator).compare(anyString(),"hello");
自定义参数匹配
@Test
public void argumentMatchersTest(){
//创建mock对象
List mock = mock(List.class);
//argThat(Matches matcher)方法用来应用自定义的规则,可以传入任何实现Matcher接口的实现类。
Mockito.when(mock.addAll(Mockito.argThat(new IsListofTwoElements()))).thenReturn(true);
Assert.assertTrue(mock.addAll(Arrays.asList("one","two","three")));
}
class IsListofTwoElements extends ArgumentMatcher
{
public boolean matches(Object list)
{
return((List)list).size()==3;
}
}
预期回调接口生成期望值
@Test
public void answerTest(){
List mockList = Mockito.mock(List.class);
//使用方法预期回调接口生成期望值(Answer结构)
Mockito.when(mockList.get(Mockito.anyInt())).thenAnswer(new CustomAnswer());
Assert.assertEquals("hello world:0",mockList.get(0));
Assert.assertEquals("hello world:999",mockList.get(999));
}
private class CustomAnswer implements Answer {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
return "hello world:"+args[0];
}
}
等价于:(也可使用匿名内部类实现)
@Test
public void answer_with_callback(){
//使用Answer来生成我们我们期望的返回
Mockito.when(mockList.get(Mockito.anyInt())).thenAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
return "hello world:"+args[0];
}
});
Assert.assertEquals("hello world:0",mockList.get(0));
Assert. assertEquals("hello world:999",mockList.get(999));
}
预期回调接口生成期望值(直接执行)
@Test
public void testAnswer1(){
List mock = Mockito.mock(List.class);
Mockito.doAnswer(new CustomAnswer()).when(mock).get(Mockito.anyInt());
Assert.assertEquals("大于三", mock.get(4));
Assert.assertEquals("小于三", mock.get(2));
}
public class CustomAnswer implements Answer {
public String answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Integer num = (Integer)args[0];
if( num>3 ){
return "大于三";
} else {
return "小于三";
}
}
}
修改对未预设的调用返回默认期望(指定返回值)
//mock对象使用Answer来对未预设的调用返回默认期望值
List mock = Mockito.mock(List.class,new Answer() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return 999;
}
});
//下面的get(1)没有预设,通常情况下会返回NULL,但是使用了Answer改变了默认期望值
Assert.assertEquals(999, mock.get(1));
//下面的size()没有预设,通常情况下会返回0,但是使用了Answer改变了默认期望值
Assert.assertEquals(999,mock.size());
用spy监控真实对象,设置真实对象行为
@Test(expected = IndexOutOfBoundsException.class)
public void spy_on_real_objects(){
List list = new LinkedList();
List spy = Mockito.spy(list);
//下面预设的spy.get(0)会报错,因为会调用真实对象的get(0),所以会抛出越界异常
//Mockito.when(spy.get(0)).thenReturn(3);
//使用doReturn-when可以避免when-thenReturn调用真实对象api
Mockito.doReturn(999).when(spy).get(999);
//预设size()期望值
Mockito.when(spy.size()).thenReturn(100);
//调用真实对象的api
spy.add(1);
spy.add(2);
Assert.assertEquals(100,spy.size());
Assert.assertEquals(1,spy.get(0));
Assert.assertEquals(2,spy.get(1));
Assert.assertEquals(999,spy.get(999));
}
不做任何返回
@Test
public void Test() {
A a = Mockito.mock(A.class);
//void 方法才能调用doNothing()
Mockito.doNothing().when(a).setName(Mockito.anyString());
a.setName("bb");
Assert.assertEquals("bb",a.getName());
}
class A {
private String name;
private void setName(String name){
this.name = name;
}
private String getName(){
return name;
}
}
调用真实的方法
@Test
public void Test() {
A a = Mockito.mock(A.class);
//void 方法才能调用doNothing()
Mockito.when(a.getName()).thenReturn("bb");
Assert.assertEquals("bb",a.getName());
//等价于Mockito.when(a.getName()).thenCallRealMethod();
Mockito.doCallRealMethod().when(a).getName();
Assert.assertEquals("zhangsan",a.getName());
}
class A {
public String getName(){
return "zhangsan";
}
}
重置 mock
@Test
public void reset_mock(){
List list = mock(List.class);
Mockito. when(list.size()).thenReturn(10);
list.add(1);
Assert.assertEquals(10,list.size());
//重置mock,清除所有的互动和预设
Mockito.reset(list);
Assert.assertEquals(0,list.size());
}
@Mock 注解
public class MockitoTest {
@Mock
private List mockList;
//必须在基类中添加初始化mock的代码,否则报错mock的对象为NULL
public MockitoTest(){
MockitoAnnotations.initMocks(this);
}
@Test
public void AnnoTest() {
mockList.add(1);
Mockito.verify(mockList).add(1);
}
}
指定测试类使用运行器:MockitoJUnitRunner
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest2 {
@Mock
private List mockList;
@Test
public void shorthand(){
mockList.add(1);
Mockito.verify(mockList).add(1);
}
}
@MockBean
使用 @MockBean 可以解决单元测试中的一些依赖问题,示例如下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class ServiceWithMockBeanTest {
@MockBean
SampleDependencyA dependencyA;
@Autowired
SampleService sampleService;
@Test
public void testDependency() {
when(dependencyA.getExternalValue(anyString())).thenReturn("mock val: A");
assertEquals("mock val: A", sampleService.foo());
}
}
@MockBean 只能 mock 本地的代码——或者说是自己写的代码,对于储存在库中而且又是以 Bean 的形式装配到代码中的类无能为力。
@SpyBean 解决了 SpringBoot 的单元测试中 @MockBean 不能 mock 库中自动装配的 Bean 的局限(目前还没需求,有需要的自己查阅资料)。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
你可能感兴趣的:(SpringBoot 单元测试实战(Mockito,MockBean))
知物由学 | AI网络安全实战:生成对抗网络
Hacker_Fuchen
人工智能 web安全 生成对抗网络
作者:BradHarris,安全研究员,Brad曾在公共和私营部门的网络和计算机安全领域工作过。他已经完成了从渗透测试到逆向工程到应用研究的所有工作,目前他是IBMX-Force的研究员。GANs是人工智能(AI)的最新思想之一。在我们深入讨论这个话题之前,让我们先来看看“对抗性”这个词的含义。在AI的原始应用中,这个词指的是用来欺骗评估神经网络或另一个机器学习模型的样本类型。随着机器学习在安全应
将SSM(Spring + SpringMVC + MyBatis) + JSP项目中的Spring重构为Spring Boot
Pan's pidr
Java后端 spring spring boot java
整体思路参考这篇博客:https://blog.csdn.net/xiaocxyczh/article/details/78681374SpringMVC到SpringBoot的简化之路https://juejin.cn/post/6844903573453537294SpringBoot与SpringMVC是两种不同的配置方式,一种是使用starter启动器来完成自动配置,另一种是在xml中进行
sqlalchemy python数据库实战 pdf_SQLALCHEMY PYTHON数据库实战(第2版)
weixin_39612817
sqlalchemy python数据库实战 pdf
SQLAlchemy是一个流行的开源代码库,功能强大又相当灵活,能够帮助Python程序员使用各种关系型数据库,许多公司甚至把SQLAlchemy看作在Python中使用关系型数据库的标准方式,使用SQLAlchemy已经成为Python程序员推荐的技能之一。1.本书为O'Reilly系列丛书,众多年来“动物书”成为广大程序员心目中的解决问题的非常不错指南;2.本书通过真实示例,一步步指导读者使用
深入理解C语言取模运算及其实战测试
一朵小小玫
本文还有配套的精品资源,点击获取简介:取模运算是C语言中进行数学计算的重要操作,使用百分号(%)表示。它主要用于获取两个整数相除的余数,并且仅适用于整数类型。本文将详细探讨取模运算的基础知识、基本用法、类型限制、负数取模行为、应用示例,以及实践意义。此外,还会提供main.c的代码示例和编译指令,帮助理解如何在实践中应用取模运算,以及如何通过编写和测试代码来加深对这一概念的理解。1.取模运算符定义
Selenium+Pytest自动化测试框架实战
测试-八戒
selenium pytest 测试工具
前言#selenium自动化+pytest测试框架本章你需要一定的python基础——至少明白类与对象,封装继承一定的selenium基础——本篇不讲selenium,不会的可以自己去看selenium中文翻译网测试框架简介#测试框架有什么优点呢:代码复用率高,如果不使用框架的话,代码会很冗余可以组装日志、报告、邮件等一些高级功能提高元素等数据的可维护性,元素发生变化时,只需要更新一下配置文件使用
selenium用法详解【从入门到实战】【Python爬虫】【4万字
m0_60635609
程序员 selenium python 爬虫
driver.find_element_by_id(‘xxx’).send_keys(Keys.ENTER)使用Backspace来删除一个字符driver.find_element_by_id(‘xxx’).send_keys(Keys.BACK_SPACE)Ctrl+A全选输入框中内容driver.find_element_by_id(‘xxx’).send_keys(Keys.CONTROL
Spring Boot 项目中如何优雅丝滑地从 Date 过渡到 LocalDateTime
墨瑾轩
一起学学Java【一】 spring boot 后端 java
关注墨瑾轩,带你探索编程的奥秘!超萌技术攻略,轻松晋级编程高手技术宝库已备好,就等你来挖掘订阅墨瑾轩,智趣学习不孤单即刻启航,编程之旅更有趣SpringBoot项目中如何优雅丝滑地从Date过渡到LocalDateTime嘿,小伙伴们!今天我们要一起探讨如何在SpringBoot项目中优雅地从使用Date类型过渡到使用LocalDateTime。如果你正在寻找一种高效的方法来更新你的项目以适应现代
【微服务】SpringBoot 整合Redis实现延时任务处理使用详解
小码农叔叔
微服务治理与实战 redis入门到精通 Redis实现延时队列 redis延时队列详解 Redis延时队列 Redis延时任务 java延时任务解决方案 redis延时任务使用
目录一、前言二、延迟任务的高频使用场景三、延迟任务常用解决方案3.1Quartz3.2DelayQueue3.2.1Timer+TimerTask3.2.2ScheduledExecutorService3.3Redissortedset3.4RabbitMQ四、Redis实现延时队列操作实战4.1RedisSortedSet概述4.1.1RedisSortedSet介绍4.1.2RedisSor
书生·浦语大模型(二)趣味demo【已体验灵笔】
ww伟
语言模型
书生·浦语大模型实战营目录书生·浦语大模型实战营(一)部署InternLM2-Chat-1.8B模型进行智能对话1、配置基础环境2、下载InternLM2-Chat-1.8B模型3、运行cli_demo(二)部署实战营优秀作品八戒-Chat-1.8B模型1、配置基础环境2、下载运行Chat-八戒Demo(三)通过InternLM2-Chat-7B运行Lagent智能体Demo(开启30%A100权
新书上线 |《零门槛AIGC应用实战——Serverless+AI 轻松玩转高频AIGC场景》免费下载
github
《零门槛AIGC应用实战——Serverless+AI轻松玩转高频AIGC场景》电子书正式上线!多种精选AI部署方案带你深入了解Serverless+AI最新趋势、AI应用的架构设计与详细的部署教程等。函数计算AI技术解决方案助您一键上云,高效部署。点击链接,即可免费下载电子书:https://developer.aliyun.com/ebook/8432现在,当我们再提到AI时,我们不仅仅是在谈
【SpringBoot】34、SpringBoot整合Redis实现序列化存储Java对象
Asurplus
SpringBoot 2.x系列 redis 序列化 springboot java对象
前面我们已经介绍过【SpringBoot】十七、SpringBoot中整合Redis,我们可以看出,在SpringBoot对Redis做了一系列的自动装配,使用还是非常方便的一、背景1、思考通过我们前面的学习,我们已经可以往Redis中存入字符串,那么我们要往Redis中存入Java对象该怎么办呢?2、方案我们可以将Java对象转化为JSON对象,然后转为JSON字符串,存入Redis,那么我们从
数仓实战05:数仓搭建-DWS层
曾牛
数仓
1.业务术语1)用户用户以设备为判断标准,在移动统计中,每个独立设备认为是一个独立用户。Android系统根据IMEI号,IOS系统根据OpenUDID来标识一个独立用户,每部手机一个用户。2)新增用户首次联网使用应用的用户。如果一个用户首次打开某APP,那这个用户定义为新增用户;卸载再安装的设备,不会被算作一次新增。新增用户包括日新增用户、周新增用户、月新增用户。3)活跃用户打开应用的用户即为活
SpringCloud03—服务治理:SpringCloud Eureka
m0_75011249
程序员 spring cloud eureka java
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!spring-boot-starter-parent2.5.1org.springframework.cloudspring-cloud-starter-eureka1.4.7.RELEASEorg.springframework.cloudspring-cloud-dependencies2020
快速入门Springboot+vue——MybatisPlus多表查询及分页查询
ONEPEICE-ing
vue.js spring boot 前端 mybatis
学习自哔哩哔哩上的“刘老师教编程”,具体学习的网站为:7.MybatisPlus多表查询及分页查询_哔哩哔哩_bilibili,以下是看课后做的笔记,仅供参考。多表查询多表查询[Mybatis中的]:实现复杂关系映射,可以使用@Results直接,@Result注解,@One注解,@Many注解组合完成复杂关系的配置。@Results:代替标签,该注解中可以加入单个或多个@Result注解@Res
【硬核对比】ReentrantReadWriteLock 被全面碾压?阿里百万级压测揭秘 StampedLock 的真实性能!
努力的靠近目标
并发编程 java
关键词:Java高并发、读写锁性能、StampedLock源码、锁优化、线程安全设计开篇暴击:一个锁的选择失误,让公司一夜损失百万!某金融系统因错误使用ReentrantReadWriteLock,导致对账延迟12小时,直接经济损失300万!同一场景改用StampedLock后,吞吐量提升6倍,延迟降低90%!本文将用源码层暴力拆解+阿里云压测数据+蚂蚁金服实战代码,深度对比两大读写锁,带你避开高
springboot2.x整合jpa
灬Change
spring boot mysql 后端 jpa java
前言为了以后需要使用jpa的时候,可以快速搭建好项目,这个例子不会玩的很全,只是为了能玩起来。源码地址:GitHub-ChangeSu/springboot-jpa-demo:springboot2.0整合jpa示例1.版本org.springframework.bootspring-boot-starter-parent2.5.6org.springframework.bootspring-bo
spring boot 发送邮件功能
??????4?A???
spring boot java 前端
邮件发送是一个非常常见的功能,注册时的身份认证、重要通知发送等都会用到邮件发送。Sun公司提供了JavaMail用来实现邮件发送,但是配置烦琐,Spring中提供了JavaMailSender用来简化邮件配置,SpringBoot则提供了MailSenderAutoConfiguration对邮件的发送做了进一步简化,本文将介绍SpringBoot如何实现邮件发送功能。一、环境配置1、导入依赖使用
清华独家教程 | 零基础玩转DeepSeek:AI时代的实战赋能手册
阿黎逸阳
学习python 人工智能 人工智能
在人工智能技术加速渗透各行各业的今天,清华大学新闻与传播学院新媒体研究中心元宇宙文化实验室的余梦珑博士后团队推出《DeepSeek从入门到精通》,为公众提供了一份权威、实用的AI工具使用指南。这份104页的文档不仅是技术手册,更是人工智能时代的效率革命指南,帮助用户从基础操作到高阶应用全面掌握DeepSeek这一通用人工智能(AGI)工具。当人人都会用AI时,你如何用得更好更出彩?一起来看看吧。
SpringBoot整合WebSocket服务
码云217
spring boot websocket 后端
1、前言2、开始使用2.1、加入Maven依赖2.2(推荐方式)使用WebSocketConfigurer方式创建WebSocket端点(二选一)2.2.1创建一个测试WebSocket处理器2.2.2开启WebSocket并且注册WebSocket处理器2.3使用ServerEndpoint方式创建WebSocket端点(二选一)2.3.1创建一个测试WebSocket处理器2.3.2开启Web
软件测试技术之iOS 单元测试—逻辑测试
学掌门
IT 软件测试 单元测试 ios junit
单元测试分为3种:逻辑测试:测试逻辑方法异步测试:测试耗时方法(用来测试包含多线程的方法)性能测试:测试某一方法运行所消耗的时间本节介绍逻辑测试,直接创建一个项目,并选中IncludeUnitTests选项。创建工程时选中UnitTests.png1.新建一个Person类,提供字典转模型的方法,这个方法就是需要进行单元测试的:+(instancetype)personWithDict:(NSDi
前端必备:正则表达式入门指南与高频场景实战
禅意码农
js 正则表达式 javascript node.js
正则表达式是处理文本的瑞士军刀,但对于新手来说可能有些复杂。本文通过通俗易懂的讲解和实用案例,带你快速上手!一、正则表达式基础组成1.修饰符(Flags)修饰符放在正则表达式末尾(如/pattern/igm),用于控制匹配模式:修饰符名称作用iignoreCase忽略大小写(如匹配"A"和"a")gglobal全局匹配(匹配所有结果,而非第一个)mmultiline多行模式(允许^和$匹配行首行尾
鸿蒙NEXT(开发进阶)通过关系型数据库实现数据持久化
你不要给我蛙蛙叫啊
鸿蒙开发 HarmonyOS OpenHarmony harmonyos 华为 鸿蒙 前端 鸿蒙系统 android 数据库
鸿蒙NEXT开发实战往期必看文章:一分钟了解”纯血版!鸿蒙HarmonyOSNext应用开发!“非常详细的”鸿蒙HarmonyOSNext应用开发学习路线!(从零基础入门到精通)HarmonyOSNEXT应用开发案例实践总结合(持续更新......)HarmonyOSNEXT应用开发性能优化实践总结(持续更新......)场景介绍关系型数据库基于SQLite组件,适用于存储包含复杂关系数据的场景,
基于Java+Spring+vue+element实现旅游信息管理平台系统
网顺技术团队
成品程序项目 java spring vue.js spring boot 课程设计
基于Java+Spring+vue+element实现旅游信息管理平台系统作者主页网顺技术团队欢迎点赞收藏⭐留言文末获取源码联系方式查看下方微信号获取联系方式承接各种定制系统精彩系列推荐精彩专栏推荐订阅不然下次找不到哟Java毕设项目精品实战案例《1000套》感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人文章目录基于Java+Spring
Vue+Jest 单元测试
arron4210
前端 vue 单元测试 vue
新到一个公司,要求单元测试覆盖率达50%以上,我们都是后补的单测,其实单测的意义是根据需求提前写好,驱动开发,代替手动测试。然鹅这只是理想。。。这里总结一下各种遇到的单测场景挂载组件,调用elementui,mock函数```javascriptdescribe('页面验证',()=>{constwrapper=getVue({component:onlineFixedPrice,callback
Python爬虫实战:从零到一构建数据采集系统
DevKevin
爬虫 python 爬虫 开发语言
文章目录前言一、准备工作1.1环境配置1.2选择目标网站二、爬虫实现步骤2.1获取网页内容2.2解析HTML2.3数据保存三、完整代码示例四、优化与扩展4.1反爬应对策略4.2动态页面处理4.3数据可视化扩展五、注意事项六、总结互动环节前言在大数据时代,数据采集是开发者的必备技能之一,而Python凭借其简洁的语法和丰富的库(如requests、BeautifulSoup)成为爬虫开发的首选语言。
HarmonyOS Next 实战开发-数据管理开发常见问题
码牛程序猿
HarmonyOS 鸿蒙工程师 鸿蒙 harmonyos 华为 鸿蒙应用开发 OpenHarmony 鸿蒙 鸿蒙系统 鸿蒙工程师
关系型数据库rdb中如何进行加密(API9)解决措施创建关系型数据库,可通过StoreConfig管理关系型数据库配置,其中encrypt属性指定数据库是否加密。关系型数据库rdb中使用TRUNCATETABLE语句无法清空表数据(API9)问题现象通过TRUNCATETABLE语句清空表数据时报错。解决措施关系型数据库rdb使用Sqlite数据库,它不支持TRUNCATETABLE语句,建议使用
Vue.js Vue 测试工具:Vue Test Utils 与 Jest
轻口味
VUE.JS 入门与实践 vue.js
Vue.jsVue测试工具:VueTestUtils与Jest在Vue.js的开发过程中,编写和执行测试是确保应用质量和稳定性的关键步骤。VueTestUtils和Jest是Vue.js官方推荐的测试工具,二者结合使用,可以高效地进行单元测试和集成测试。1.VueTestUtils简介VueTestUtils(VTU)是Vue.js官方提供的测试实用工具库,旨在简化Vue组件的测试工作。它提供了一
软件单元测试的技术要求
嵌入式软件测试开发
软测理论 单元测试
文章目录一、软件单元测试的概念二、测试对象三、测试目的四、进入条件五、测试内容六、测试环境七、测试实施方一、软件单元测试的概念单元测试(UnitTesting),是指对软件中的最小可测试单元进行测试验证。单元测试是白盒测试,主要依据软件详细设计和软件代码进行,不仅要求验证软件设计的功能,还要求对软件代码的覆盖率进行测试。概要的单元测试流程如下:二、测试对象单元测试的对象是具有输入输出、完成特定功能
SpringBoot 版本 与 Spring 与JDK 版本 与 maven 兼容问题
wei198621
maven_gradle Spring maven spring boot spring
转自大牛https://blog.csdn.net/wangqing84411433/article/details/90634603SpringBoot版本SpringFrameworkjdk版本maven版本1.2.0版本之前63.01.2.04.1.3+63.2+1.2.14.1.3+73.2+1.2.34.1.5+73.2+1.3.44.2.6+73.2+1.3.64.2.7+73.2+1
《Linux系统编程篇》System V信号量(Linux 进程间通信(IPC))——基础篇
家驹嵌入式
从0开始学linux linux
文章目录引言**Linux中的SystemV信号量:基础与实战****SystemV信号量简介****关键概念**️**SystemV信号量的相关函数****函数原型**1.`semget()`—创建或获取信号量集2.`semop()`—执行信号量操作3.`semctl()`—控制信号量集4.`semctl()`—删除信号量集**示例:基本的信号量操作****解析****进阶实例:生产者-消费者
java的(PO,VO,TO,BO,DAO,POJO)
Cb123456
VO TO BO POJO DAO
转:
http://www.cnblogs.com/yxnchinahlj/archive/2012/02/24/2366110.html
-------------------------------------------------------------------
O/R Mapping 是 Object Relational Mapping(对象关系映
spring ioc原理(看完后大家可以自己写一个spring)
aijuans
spring
最近,买了本Spring入门书:spring In Action 。大致浏览了下感觉还不错。就是入门了点。Manning的书还是不错的,我虽然不像哪些只看Manning书的人那样专注于Manning,但怀着崇敬 的心情和激情通览了一遍。又一次接受了IOC 、DI、AOP等Spring核心概念。 先就IOC和DI谈一点我的看法。IO
MyEclipse 2014中Customize Persperctive设置无效的解决方法
Kai_Ge
MyEclipse2014
高高兴兴下载个MyEclipse2014,发现工具条上多了个手机开发的按钮,心生不爽就想弄掉他!
结果发现Customize Persperctive失效!!
有说更新下就好了,可是国内Myeclipse访问不了,何谈更新...
so~这里提供了更新后的一下jar包,给大家使用!
1、将9个jar复制到myeclipse安装目录\plugins中
2、删除和这9个jar同包名但是版本号较
SpringMvc上传
120153216
springMVC
@RequestMapping(value = WebUrlConstant.UPLOADFILE)
@ResponseBody
public Map<String, Object> uploadFile(HttpServletRequest request,HttpServletResponse httpresponse) {
try {
//
Javascript----HTML DOM 事件
何必如此
JavaScript html Web
HTML DOM 事件允许Javascript在HTML文档元素中注册不同事件处理程序。
事件通常与函数结合使用,函数不会在事件发生前被执行!
注:DOM: 指明使用的 DOM 属性级别。
1.鼠标事件
属性
动态绑定和删除onclick事件
357029540
JavaScript jquery
因为对JQUERY和JS的动态绑定事件的不熟悉,今天花了好久的时间才把动态绑定和删除onclick事件搞定!现在分享下我的过程。
在我的查询页面,我将我的onclick事件绑定到了tr标签上同时传入当前行(this值)参数,这样可以在点击行上的任意地方时可以选中checkbox,但是在我的某一列上也有一个onclick事件是用于下载附件的,当
HttpClient|HttpClient请求详解
7454103
apache 应用服务器 网络协议 网络应用 Security
HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。本文首先介绍 HTTPClient,然后根据作者实际工作经验给出了一些常见问题的解决方法。HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需
递归 逐层统计树形结构数据
darkranger
数据结构
将集合递归获取树形结构:
/**
*
* 递归获取数据
* @param alist:所有分类
* @param subjname:对应统计的项目名称
* @param pk:对应项目主键
* @param reportList: 最后统计的结果集
* @param count:项目级别
*/
public void getReportVO(Arr
访问WEB-INF下使用frameset标签页面出错的原因
aijuans
struts2
<frameset rows="61,*,24" cols="*" framespacing="0" frameborder="no" border="0">
MAVEN常用命令
avords
Maven库:
http://repo2.maven.org/maven2/
Maven依赖查询:
http://mvnrepository.com/
Maven常用命令: 1. 创建Maven的普通java项目: mvn archetype:create -DgroupId=packageName
PHP如果自带一个小型的web服务器就好了
houxinyou
apache 应用服务器 Web PHP 脚本
最近单位用PHP做网站,感觉PHP挺好的,不过有一些地方不太习惯,比如,环境搭建。PHP本身就是一个网站后台脚本,但用PHP做程序时还要下载apache,配置起来也不太很方便,虽然有好多配置好的apache+php+mysq的环境,但用起来总是心里不太舒服,因为我要的只是一个开发环境,如果是真实的运行环境,下个apahe也无所谓,但只是一个开发环境,总有一种杀鸡用牛刀的感觉。如果php自己的程序中
NoSQL数据库之Redis数据库管理(list类型)
bijian1013
redis 数据库 NoSQL
3.list类型及操作
List是一个链表结构,主要功能是push、pop、获取一个范围的所有值等等,操作key理解为链表的名字。Redis的list类型其实就是一个每个子元素都是string类型的双向链表。我们可以通过push、pop操作从链表的头部或者尾部添加删除元素,这样list既可以作为栈,又可以作为队列。
&nbs
谁在用Hadoop?
bingyingao
hadoop 数据挖掘 公司 应用场景
Hadoop技术的应用已经十分广泛了,而我是最近才开始对它有所了解,它在大数据领域的出色表现也让我产生了兴趣。浏览了他的官网,其中有一个页面专门介绍目前世界上有哪些公司在用Hadoop,这些公司涵盖各行各业,不乏一些大公司如alibaba,ebay,amazon,google,facebook,adobe等,主要用于日志分析、数据挖掘、机器学习、构建索引、业务报表等场景,这更加激发了学习它的热情。
【Spark七十六】Spark计算结果存到MySQL
bit1129
mysql
package spark.examples.db
import java.sql.{PreparedStatement, Connection, DriverManager}
import com.mysql.jdbc.Driver
import org.apache.spark.{SparkContext, SparkConf}
object SparkMySQLInteg
Scala: JVM上的函数编程
bookjovi
scala erlang haskell
说Scala是JVM上的函数编程一点也不为过,Scala把面向对象和函数型编程这两种主流编程范式结合了起来,对于熟悉各种编程范式的人而言Scala并没有带来太多革新的编程思想,scala主要的有点在于Java庞大的package优势,这样也就弥补了JVM平台上函数型编程的缺失,MS家.net上已经有了F#,JVM怎么能不跟上呢?
对本人而言
jar打成exe
bro_feng
java jar exe
今天要把jar包打成exe,jsmooth和exe4j都用了。
遇见几个问题。记录一下。
两个软件都很好使,网上都有图片教程,都挺不错。
首先肯定是要用自己的jre的,不然不能通用,其次别忘了把需要的lib放到classPath中。
困扰我很久的一个问题是,我自己打包成功后,在一个同事的没有装jdk的电脑上运行,就是不行,报错jvm.dll为无效的windows映像,如截图
最后发现
读《研磨设计模式》-代码笔记-策略模式-Strategy
bylijinnan
java 设计模式
声明: 本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
/*
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化
简单理解:
1、将不同的策略提炼出一个共同接口。这是容易的,因为不同的策略,只是算法不同,需要传递的参数
cmd命令值cvfM命令
chenyu19891124
cmd
cmd命令还真是强大啊。今天发现jar -cvfM aa.rar @aaalist 就这行命令可以根据aaalist取出相应的文件
例如:
在d:\workspace\prpall\test.java 有这样一个文件,现在想要将这个文件打成一个包。运行如下命令即可比如在d:\wor
OpenJWeb(1.8) Java Web应用快速开发平台
comsci
java 框架 Web 项目管理 企业应用
OpenJWeb(1.8) Java Web应用快速开发平台的作者是我们技术联盟的成员,他最近推出了新版本的快速应用开发平台 OpenJWeb(1.8),我帮他做做宣传
OpenJWeb快速开发平台以快速开发为核心,整合先进的java 开源框架,本着自主开发+应用集成相结合的原则,旨在为政府、企事业单位、软件公司等平台用户提供一个架构透
Python 报错:IndentationError: unexpected indent
daizj
python tab 空格 缩进
IndentationError: unexpected indent 是缩进的问题,也有可能是tab和空格混用啦
Python开发者有意让违反了缩进规则的程序不能通过编译,以此来强制程序员养成良好的编程习惯。并且在Python语言里,缩进而非花括号或者某种关键字,被用于表示语句块的开始和退出。增加缩进表示语句块的开
HttpClient 超时设置
dongwei_6688
httpclient
HttpClient中的超时设置包含两个部分:
1. 建立连接超时,是指在httpclient客户端和服务器端建立连接过程中允许的最大等待时间
2. 读取数据超时,是指在建立连接后,等待读取服务器端的响应数据时允许的最大等待时间
在HttpClient 4.x中如下设置:
HttpClient httpclient = new DefaultHttpC
小鱼与波浪
dcj3sjt126com
一条小鱼游出水面看蓝天,偶然间遇到了波浪。 小鱼便与波浪在海面上游戏,随着波浪上下起伏、汹涌前进。 小鱼在波浪里兴奋得大叫:“你每天都过着这么刺激的生活吗?简直太棒了。” 波浪说:“岂只每天过这样的生活,几乎每一刻都这么刺激!还有更刺激的,要有潮汐变化,或者狂风暴雨,那才是兴奋得心脏都会跳出来。” 小鱼说:“真希望我也能变成一个波浪,每天随着风雨、潮汐流动,不知道有多么好!” 很快,小鱼
Error Code: 1175 You are using safe update mode and you tried to update a table
dcj3sjt126com
mysql
快速高效用:SET SQL_SAFE_UPDATES = 0;下面的就不要看了!
今日用MySQL Workbench进行数据库的管理更新时,执行一个更新的语句碰到以下错误提示:
Error Code: 1175
You are using safe update mode and you tried to update a table without a WHERE that
枚举类型详细介绍及方法定义
gaomysion
enum javaee
转发
http://developer.51cto.com/art/201107/275031.htm
枚举其实就是一种类型,跟int, char 这种差不多,就是定义变量时限制输入的,你只能够赋enum里面规定的值。建议大家可以看看,这两篇文章,《java枚举类型入门》和《C++的中的结构体和枚举》,供大家参考。
枚举类型是JDK5.0的新特征。Sun引进了一个全新的关键字enum
Merge Sorted Array
hcx2013
array
Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
Note:You may assume that nums1 has enough space (size that is
Expression Language 3.0新特性
jinnianshilongnian
el 3.0
Expression Language 3.0表达式语言规范最终版从2013-4-29发布到现在已经非常久的时间了;目前如Tomcat 8、Jetty 9、GlasshFish 4已经支持EL 3.0。新特性包括:如字符串拼接操作符、赋值、分号操作符、对象方法调用、Lambda表达式、静态字段/方法调用、构造器调用、Java8集合操作。目前Glassfish 4/Jetty实现最好,对大多数新特性
超越算法来看待个性化推荐
liyonghui160com
超越算法来看待个性化推荐
一提到个性化推荐,大家一般会想到协同过滤、文本相似等推荐算法,或是更高阶的模型推荐算法,百度的张栋说过,推荐40%取决于UI、30%取决于数据、20%取决于背景知识,虽然本人不是很认同这种比例,但推荐系统中,推荐算法起的作用起的作用是非常有限的。
就像任何
写给Javascript初学者的小小建议
pda158
JavaScript
一般初学JavaScript的时候最头痛的就是浏览器兼容问题。在Firefox下面好好的代码放到IE就不能显示了,又或者是在IE能正常显示的代码在firefox又报错了。 如果你正初学JavaScript并有着一样的处境的话建议你:初学JavaScript的时候无视DOM和BOM的兼容性,将更多的时间花在 了解语言本身(ECMAScript)。只在特定浏览器编写代码(Chrome/Fi
Java 枚举
ShihLei
java enum 枚举
注:文章内容大量借鉴使用网上的资料,可惜没有记录参考地址,只能再传对作者说声抱歉并表示感谢!
一 基础 1)语法
枚举类型只能有私有构造器(这样做可以保证客户代码没有办法新建一个enum的实例)
枚举实例必须最先定义
2)特性
&nb
Java SE 6 HotSpot虚拟机的垃圾回收机制
uuhorse
java HotSpot GC 垃圾回收 VM
官方资料,关于Java SE 6 HotSpot虚拟机的garbage Collection,非常全,英文。
http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html
Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning
&