目录
一个测试方法主要包括三部分
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))
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()`—删除信号量集**示例:基本的信号量操作****解析****进阶实例:生产者-消费者
硬刚Android Jetpack:3万字全面指南与应用实践大揭秘
大模型大数据攻城狮
android面试 LiveData android jetpack room viewmodel android电量 workmanager
目录一、Jetpack概述(一)组件架构大剖析(二)优势特点大放送二、核心组件应用(一)ViewModel使用全攻略(二)LiveData实践秘籍(三)Room数据库深度解析(四)DataBinding技术详解三、UI开发指南(一)ConstraintLayout布局深度探索(二)Compose界面构建全解析(三)Navigation导航组件探秘四、后台任务处理(一)WorkManager应用实战
网络安全竞赛学习路线及建议
星光网络安全社
规划 web安全 学习 安全 网络安全
参加网络安全竞赛(如CTF、攻防赛等)需要掌握广泛的知识和技能。以下是我所整理的网络安全竞赛的学习内容,涵盖基础知识、进阶技能和实战训练。(ps:参加竞赛与就业侧重点不同,竞赛主要是精细化、模块化的专项训练)一、基础知识1.计算机基础操作系统:Linux(常用命令、文件系统、权限管理)、Windows(注册表、服务管理)计算机网络:TCP/IP协议、HTTP/HTTPS、DNS、ARP、路由与交换
使用RabbitMQ实现异步消息处理与解耦:Spring Boot整合实践
MarkerHub
java-rabbitmq rabbitmq spring boot 分布式 后端
前后端微服务商城项目,手把手教学!在现代应用架构中,异步消息处理和解耦是提高系统性能、扩展性和维护性的关键技术手段。RabbitMQ作为一种流行的消息队列中间件,提供了可靠、高效、灵活的消息传递功能,广泛应用于分布式系统和微服务架构中。本文将带你走进SpringBoot与RabbitMQ的整合实践,帮助你实现异步消息处理和系统解耦。通过这一过程,你将能够轻松地实现消息传递的异步化,提升系统的响应速
利用爬虫获取淘宝商品描述:实战案例指南
数据小小爬虫
爬虫
在电商领域,商品描述是消费者了解产品细节、做出购买决策的重要依据。精准获取淘宝商品描述不仅能帮助商家优化产品信息,还能为市场研究和数据分析提供丰富的数据资源。本文将详细介绍如何利用爬虫技术精准获取淘宝商品描述,并分享关键技术和代码示例。一、前期准备(一)环境搭建确保你的开发环境已安装以下必要的库:HttpClient:用于发送HTTP请求。Jsoup:用于解析HTML页面。JSON处理库:如org
最新报告:深度解读中国车企海外业务的人才布局
汽车电子工具智慧库
汽车 Autosar
目录往期推荐报告详情更多推荐往期推荐ETAS工具链自动化实战指南<一>ETAS工具链自动化实战指南<二>ETAS工具链自动化实战指南<三>AUTOSAR工程师必读:Artop的核心功能Vector工具链自动化实战指南<一>isolar高手秘籍|ECUConfiguration三分钟速成!掌握核心步骤:RTA-BSW以太网配置全解析一文详解TC399CANMCAL配置LSL常见应用场景及示例<一>L
专栏简介:从入门到精通 JavaScript 1000例实战开发
小蘑菇二号
入门到精通 JavaScript 1000例实战开发 JavaScript 开发语言
目录专栏简介:从入门到精通JavaScript1000例实战开发专栏特色目标受众学习收获专栏目录:从入门到精通JavaScript1000例实战开发第一部分:JavaScript基础篇第二部分:JavaScript核心进阶篇第三部分:前端框架与库篇第四部分:高级实战篇第五部分:前沿技术篇附录专栏简介:从入门到精通JavaScript1000例实战开发本专栏旨在为开发者提供一套系统化的学习路径,帮助
FocusSearch/focus_mcp_sql实战:低成本实现精准自然语言转SQL指南
mysql数据库
最近在GitHub上逛的时候,发现了一个挺有意思的项目——FocusSearch/focus_mcp_sql。作为一个对Text2SQL有点小研究的前端码农,我忍不住想和大家聊聊这个工具。它不像那些常见的基于大模型的框架那样“高大上”,反而用了一种更接地气的思路解决问题。接下来,我就从Text2SQL的老故事讲起,带你看看这个项目能干啥,顺便设想一个场景,最后再唠唠为啥我觉得它值得开发者试一试。T
Vue 3最新组件解析与实践指南:提升开发效率的利器
Aic山鱼
vue.js 前端 javascript
目录引言一、Vue3核心组件特性解析1.CompositionAPI与组件逻辑复用2.内置组件与生命周期优化3.新一代UI组件库推荐二、高级组件开发技巧1.插件化架构设计2.跨层级组件通信三、性能优化实战1.惰性计算与缓存策略2.虚拟滚动与列表优化3.TreeShaking与按需引入四、总结作者:Aic山鱼|2025年2月17日作者推荐:"近期我偶然邂逅了一个极为出色的人工智能学习平台,它不仅内容
Spring全面详解:架构体系演变及其入门(学习总结)
小夕Coding
大数据系列 spring java 大数据 javabean spring boot
文章目录架构体系演变背景单一应用架构垂直应用架构分布式服务架构流动计算架构入门配置文件yaml语法快速入门基本格式要求对象数组常量一些特殊符号使用yaml进行配置注解学习反射获取注解配置文件优先级存放目录Application属性文件,按优先级排序,位置高的将覆盖位置读取顺序web开发嵌入式Servlet容器支持扫描Servlet,过滤器和listeners1、springboot整合servle
SpringBoot自动配置过程中的注册配置类的源码
一个儒雅随和的男子
spring spring boot 后端 java
SpringBoot的自动配置是其核心特性之一,通过条件化配置和约定优于配置的设计思想,自动加载和注册所需的配置类。以下从源码角度详细解析自动配置过程中注册配置类的关键步骤:一、自动配置的核心流程启动类标注@SpringBootApplication:该注解组合了@EnableAutoConfiguration,触发自动配置逻辑。加载spring.factories文件:从所有依赖的META-IN
SpringBoot3.0.3集成Redisson3.20.0
青阳科技
SpringBoot3.0.3 spring boot redis 分布式
一、概述使用SpringBoot构建分布式应用程序时,常常需要实现分布式锁、分布式限流、分布式任务调度和分布式缓存等功能,这些功能都可以通过Redis来实现。而Redisson是一个优秀的Redis客户端,它提供了丰富的分布式功能,可以帮助我们更方便地实现这些功能。那么,SpringBoot集成Redisson后我们可以实现哪些功能?1.分布式锁在分布式系统中,多个节点可能会同时对同一个资源进行修
springboot整合redisson实现分布式锁及布隆过滤器
lncy1991
工作记录 redis 过滤器 spring
下载安装redisson整合maven添加依赖使用的版本是3.13,因为springboot使用的是2.1.3版本,因此按照官方上的提示,移除redisson-spring-data-22org.springframework.bootspring-boot-starter-data-redisorg.redissonredisson-spring-boot-starterorg.redisson
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
&