Mockito单元测试

文章目录
  • Mockito单元测试
    • 为什么要使用Mock?
    • 导入依赖
    • import导入包
    • 使用Mock模拟测试某个类中的某个方法是否可以成功执行
    • 使用Mock模拟某个类的方法,自己给这个方法返回我们指定的值
    • 使用Mock模拟某个方法调用后会抛出指定的异常
    • 使用Mock模拟测试某个类中的某个方法(加上参数)调用的次数
    • 使用@Mock注解生成模拟对象
    • 疑惑?心得。
      • 注意自测的方法传递的参数会对打桩产生影响
      • 什么叫做打桩?以及什么情况下需要打桩什么情况下不需要打桩?
      • 打桩的时候返回不同的结果单测的结果可能不同
      • 上次的编译可能会影响以后的代码执行
    • 公司使用Mockito单测的格式规范
    • 我们单测的方法该怎么写?
      • 真实方法
      • 单测方法
      • 需要注意的一些细节
      • 真实方法也会使用我们模拟的返回值
    • assert关键字的作用
    • any()匹配器如果要用那么所有的参数都需要用
    • 测试的实际方法在模拟调用的时候一定要有参数不能写成any()
    • 打桩的时候到底需不需要模拟返回值?
    • 进行单测前需要考虑什么
    • 需要单测的方法调用了其它A方法,我们只需要考虑A方法中最后一个打桩的模拟数据即可
    • 工具类该如何打桩(也即是模拟调用工具类里面的静态方法其实是模拟调用静态方法)
    • 不用使用verify()方法,后面不用方法的返回值,就把方法直接去掉,不需要打桩
    • 不需要打桩的情景
    • 可以直接在方法的最外部进行打桩
    • 原始方法所用到的所有的对象都需要在模拟方法对应的类里面使用@Mock注解一下,为了使真实方法中可以找得到这个模拟对象,要不然会出现空指针异常
    • 查看覆盖率
    • 使用jacoco在浏览器查看覆盖率的方法
      • 引入jacoco插件坐标
      • 引入mockito的坐标
      • 在Mockito单元测试的配置文件中对写好的单元测试类进行配置
      • 输入maven命令
      • 浏览器打开index.html的效果
      • 特别注意一个容易出错的点
    • 通过jacoco生成的单测视图总结打桩规则
    • 除了打桩when和verify不要使用any()参数匹配器
    • 模拟构造器
    • 使用any()参数匹配器不能代替基本类型,只能代替对象类型,否则会报空指针错误
    • 原方法中后续如果用不到它的返回值,我们可以不用打桩,可以什么都不用做
    • 模拟的类一定要进行close掉

Mockito单元测试

为什么要使用Mock?

比如你现在想要测试一个方法是否是正常的,但是这个方法中有很多调用数据库的代码,那么我们就可以在每个调用数据库的地方打桩,模拟一下访问完数据库之后的返回值,这样我们就可以在测试的时候避免访问数据库了,可以非常高效地完成我们的单元测试,已达到验证我们写的方法到底对不对的目的。

在这里插入图片描述

先试想一个这样的场景,如果想要模拟一个人被车撞之后,会出现什么样的运动轨迹,那我们要做实验的时候肯定是不能用一个活生生的人做实验的对不对?

我们的Mock模拟对象也是一样的,因为真实对象由于一些原因很难被拿来直接做测试,所以我们就必须要模拟一个和真实对象一样的对象,那这个模拟的对象做测试,而Mock就是用来模拟对象的。

那么对象在什么时候是不方便被直接拿来做实验的啊?你比如:

  • 真实对象的行为很难触发(例如,网络错误);
  • 真实对象速度很慢(例如,一个完整的数据库,在测试之前可能需要初始化);

导入依赖

我们的Mockito单元测试需要配合Junit单元测试一起使用,因此首先我们需要导入这两个依赖,如下图:

在这里插入图片描述

<dependencies>
    <!--导入Mockito单元测试依赖-->
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-all</artifactId>
        <version>1.9.5</version>
        <scope>test</scope>
    </dependency>

    <!--导入junit单元测试依赖-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
</dependencies>

import导入包

在这里插入图片描述

使用Mock模拟测试某个类中的某个方法是否可以成功执行

如果我们想要测试某个类中的某个方法是否可以执行,我们不用直接调用这个类的这个方法,我们可以模拟一下这个类,让模拟的对象调用这个方法,然后再去检验一下这个模拟对象是否成功的调用到了这个方法,只要这个模拟对象成功调用到了这个方法,那么就说明,我们真实类中的这个方法是可以被成功执行的。这就是使用mockito来进行某个类的单元测试,如下图:

在这里插入图片描述

/**
 * 通过mock模拟一个对象,然后检验这个对象的某个方法是否可以执行
 * */
@Test
public void test1(){
    //模拟创建一个List对象
    List mock = mock(List.class);

    //使用mock模拟出来的List对象,让这个对象添加一个元素1,(我们其实是为了验证List类中的add方法是否正常)
    mock.add(1);

    //验证模拟的对象List的add(1)方法是否执行,如果正常发生了,说明List类中的add(1)方法是正常的。这样我们的单元测试就算通过,
    //verify()的作用主要是检验我们模拟出来的这个对象中的方法是否成功执行,如果成功执行控制台什么信息都没有,如果没有成功
    //执行,控制台会报错误信息
    verify(mock).add(1);
}

使用Mock模拟某个类的方法,自己给这个方法返回我们指定的值

我们在测试一个控制器中的方法的时候,这个控制器中肯定是有一些方法是需要访问数据库的,但是我们自己在进行单元测试的时候,其实不必访问数据库,我们只需要知道访问数据库之后得到的这个值是什么,所以我们就可以使用Mock来模拟出访问数据库的方法返回的值,下面的这个例子就是我们自己给某个类中的方法直接指定一个返回值,如下图:

在这里插入图片描述

/**
 * 模拟对象中的某个方法,给这个方法指定一个返回值,那么我们再执行这个模拟对象的方法的时候,返回的值就不再是真实
 * 对象返回的值,而应该是我们自己设置的返回值。
 *
 * 比如我们这里有一个Iterator迭代器,原本调用迭代器对象的next()方法之后返回的值是集合中的下一个元素,我们这里来模拟
 * 这个方法的返回值,模拟的是第一次调用next()方法返回值是"hello",第二次调用next()方法返回值是"world",第三次以及往后调用
 * next()方法返回值是"abc"
 *
 * 使用到了when(),thenReturn()方法,第一个thenReturn()代表第一次执行iterator.next()方法的返回值是"hello",
 * 第二个thenReturn()代表第二次执行iterator.next()方法的返回值是"world",
 * 第三个thenReturn()代表第三次即以后执行iterator.next()方法的返回值都是"abc"
 *
 * 还是用到了assertEquals(猜想值,变量)断言方法
 * */
@Test
public void test2(){
    //使用mock模拟出一个Iterator类
    Iterator iterator = mock(Iterator.class);

    //自己设置迭代器对象方法next()的返回值
    when(iterator.next()).thenReturn("hello").thenReturn("world").thenReturn("abc");

    //使用mock模拟的iterator对象,去看看iterator调用next()方法之后的返回值是否是我们想的那样
    String result = iterator.next() + " " + iterator.next() + " " + iterator.next()+" "+iterator.next();

    //使用断言验证猜想的结果是否正确
    assertEquals("hello world abc abc",result);
}

使用Mock模拟某个方法调用后会抛出指定的异常

在这里插入图片描述

/**
 * 使用Mock模拟对象,规定某个方法要抛出一个异常
 * */
@Test(expected = IOException.class)
public void test3() throws IOException {
    OutputStream outputStream = mock(OutputStream.class);

    //我们自己规定当执行OutputStream对象的close()方法的时候,会主动的抛出一个IOException异常
    doThrow(new IOException()).when(outputStream).close();

    outputStream.close();
}

使用Mock模拟测试某个类中的某个方法(加上参数)调用的次数

在这里插入图片描述

/**
 * 模拟类中的某个方法(加上对应的参数)调用的次数
 *
 * times(次数)表示调用几次
 * never()表示从没有调用过
 * atLeastOnce()表示至少调用多少1次
 * atLeast(次数)表示至少调用n次
 * atMost(次数)表示最多调用n次
 * */
@Test
public void test5(){
    List list = mock(List.class);
    list.add(1);
    list.add(2);
    list.add(2);
    list.add(3);
    list.add(3);
    list.add(3);
    //验证是否被调用一次,等效于下面的times(1)
    verify(list).add(1);
    verify(list,times(1)).add(1);
    //验证是否被调用2次
    verify(list,times(2)).add(2);
    //验证是否被调用3次
    verify(list,times(3)).add(3);
    //验证是否从未被调用过
    verify(list,never()).add(4);
    //验证至少调用一次
    verify(list,atLeastOnce()).add(1);
    //验证至少调用2次
    verify(list,atLeast(2)).add(2);
    //验证至多调用3次
    verify(list,atMost(3)).add(3);
}

使用@Mock注解生成模拟对象

在这里插入图片描述

/**
 * @Date 2021/11/10 15:47
 * @Author 望轩
 *
 * 使用@Mock注解生成一个模拟对象,注意这样的话必须要在加上一个注解@RunWith(MockitoJUnitRunner.class),
 * 要不然的话应用到的mockList或者是iterator会是null值
 */
@RunWith(MockitoJUnitRunner.class)
public class MockitoTest2 {
    @Mock
    private List mockList;

    @Mock
    private Iterator iterator;

    @Test
    public void test1(){
        mockList.add(1);
        verify(mockList).add(1);
    }

    @Test
    public void test2(){
        iterator.next();
        verify(iterator).next();
    }
}

疑惑?心得。

注意自测的方法传递的参数会对打桩产生影响

我们打桩其实是在真实方法的内部对应的位置进行打桩的,如果真实方法的对应的真实代码不会执行,那么我们在单测的时候,打桩就无效。你比如说,我们现在想要在真实方法的if判断体里面打一个桩,如果这个if判断体一直不成立,我们我们在单元测试方法中打的桩就不会替换掉真实代码中的具体位置。解释过程如下图:

在这里插入图片描述

在这里插入图片描述

下图这个异常可以通过上图来解答:

在这里插入图片描述

在这里插入图片描述

什么叫做打桩?以及什么情况下需要打桩什么情况下不需要打桩?

打桩其实就是在真实代码的地方用一个模拟方法代替,然后真实方法执行到这个地方的时候,它的返回值是我们模拟的返回值。when().thenReturn(),用这句代码我们可以自己给某个方法设定返回值,这就叫做打桩。

在什么时候需要打桩呢?如果我们想要自测的方法有返回值,我们需要打桩,如下图:

在这里插入图片描述

在这里插入图片描述

什么时候不需要打桩呢?当我们想要测试的方法没有返回值的时候,这个时候我们就不用打桩了,但是我们需要检测一下这个方法是否执行了,如下图:

在这里插入图片描述

在这里插入图片描述

打桩的时候返回不同的结果单测的结果可能不同

比如现在有一个需求,就是我们在增加期间的时候,数据库中不能存在这个期间,要不然就增加失败,在真实方法中的代码表现如下图:

在这里插入图片描述

单测的代码如下图:

在这里插入图片描述

上次的编译可能会影响以后的代码执行

在这里插入图片描述

我们提示的异常信息上面还有一个LocalDateTime日期类,但是我们之前明明已经把我们的LocalDateTime日期类改成了Date日期类,那么还报我们在项目中使用了LocalDateTime日期类,这是为什么呢?可能是因为我们的工程没有重新编译,我们现在使用的还是之间没有改成Date的字节码,所以才会出现上面的异常。这个时候我们要做的就是把Parent父工程重新clean一下,然后在重新运行我们的单元测试方法。

clean完parent父工程之后,重新测试单测方法,执行成功。

公司使用Mockito单测的格式规范

首先我们的单测代码都是写在deploy工程的test包下面的,如下图:

在这里插入图片描述

我们写的单测类必须要继承一个类并且也要使用到一个注解,如下图:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

我们单测的方法该怎么写?

比如我们举一个例子,我们举一个测试真实方法的例子。

真实方法

首先来看一下我们真实的方法是什么样子的,如下图:

在这里插入图片描述

单测方法

然后我们再来看一下我们单测的方法是什么样子的,如下图:

在这里插入图片描述

需要注意的一些细节

如下图:

在这里插入图片描述

总之就是,我们单测方法里面的模拟返回值必须要符合真实方法中的逻辑,要不然真实方法会报异常,我们的单测就不能通过。

真实方法也会使用我们模拟的返回值

有的时候真实方法中也需要用到我们的单测方法中模拟出来的返回值,如下图:

在这里插入图片描述

在这里插入图片描述

assert关键字的作用

assert关键字可以终止程序正常运行,assert关键字的作用是断言,如果它发现后面是true,那么程序可以正常运行,但是如果它发现后面是false,那么它会主动抛出一个异常并终止正在运行的程序。
在这里插入图片描述

any()匹配器如果要用那么所有的参数都需要用

打桩的时候,如果给一个参数用了匹配器any(),那么其它的参数也必须都用any()匹配器,如下图:

在这里插入图片描述

测试的实际方法在模拟调用的时候一定要有参数不能写成any()

首先为什么会有单测?主要是因为我们程序不想要访问数据库,所以我们就可以模拟一下访问数据库的操作。

单测的时候,调用我们要测试的方法的时候,一定要有实际的参数,如下图:

在这里插入图片描述

打桩的时候到底需不需要模拟返回值?

单测的时候,如果我们想要打桩的地方,它的返回值会被其它地方用到,并且它的返回值的某个属性如果没有或者格式不正确还会出现异常,那么这个时候,我们就一定要打桩模拟一个返回值,如下图:

在这里插入图片描述

在这里插入图片描述

如果打桩的时候不需要返回值,我们可以这样写,如下图:

在这里插入图片描述

不需要返回值,也可以使用doNothing(),如下图:

在这里插入图片描述

进行单测前需要考虑什么

在进行单测的时候,先把我们这个方法所用到的数据库里面的数据写在一张纸上面,成功写下所有的模拟数据之后,再进行单测代码的编写。

在这里插入图片描述

在进行单测的时候,首先要知道这个方法主要是干什么的,比如我做的一个单测导入功能,首先我需要先清楚导入这个方法需要从数据库里面查询的数据格式。比如这里从数据库里查询的数据格式有部门树,和科目树,所以我们就模拟了两个部门对象,一个是一级部门,另外一个是二级部门,如下图:

在这里插入图片描述

然后打桩的时候直接返回这些模拟数据,如下图:

在这里插入图片描述

然后模拟了三个科目,分别是一级,二级,三级科目,并且在打桩的时候直接返回模拟数据,如下图:

在这里插入图片描述

并且如果这些模拟对象存在某种逻辑关系我们也要指明,比如在部门树里,一级部门就必须是二级部门的父级如下图:

在这里插入图片描述

在科目树里我们也指明了它们的关系,如下图:

在这里插入图片描述

需要单测的方法调用了其它A方法,我们只需要考虑A方法中最后一个打桩的模拟数据即可

这里是导入方法importFromExcel()里面调用了getAllBudgetReportCategories(Long annualId),我们只需要关心这个方法需要返回什么数据给importFromExcel()方法才算合理就行了,最后把这个合理数据模拟出来。所以这个方法的前两个地方打桩的时候,它返回的模拟数据不用太多规范只要能保证后面能不报异常就行,但是最后一个打桩的地方,它返回的模拟数据必须要合理,因为它返回的模拟数据会被importFromExcel()后面的部分用到,所以所有打桩的模拟数据之间必须要相互匹配。

一个方法中如果有多个节点需要打桩,我们只需要关心最后一个需要打桩的地方它的模拟数据,至于前面需要打桩的地方,它返回的模拟数据我们不需要关心,但是要保证前面的这个打桩后的模拟数据能够保证后面能成功运行就行了。我们想一下我们调用这个方法的时候,想要让这个方法返回什么数据,那么在打桩的时候我们就模拟返回什么数据,如下图:

在这里插入图片描述

工具类该如何打桩(也即是模拟调用工具类里面的静态方法其实是模拟调用静态方法)

在这里插入图片描述

我们可以使用静态模拟类的方式进行打桩,如下图:

在这里插入图片描述
注意:
在这里插入图片描述
如果工具类中的静态方法没有返回值,我们直接模拟一下工具类就行了,不需要对静态方法进行打桩,如下图:
在这里插入图片描述

不用使用verify()方法,后面不用方法的返回值,就把方法直接去掉,不需要打桩

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

那像我们这种返回值不会被后面用到的方法,在打桩的时候应该如何打桩呢?像这种方法不用打桩,我们直接去掉就行了。如下图:

在这里插入图片描述

不需要打桩的情景

如果原本的方法中的访问数据库的方法后面不需要用到它的返回值,那么我们可以不用打桩,什么都不用写,如下图:

在这里插入图片描述

在这里插入图片描述

可以直接在方法的最外部进行打桩

在这里插入图片描述

在这里插入图片描述

打桩方法如下图:

在这里插入图片描述

原始方法所用到的所有的对象都需要在模拟方法对应的类里面使用@Mock注解一下,为了使真实方法中可以找得到这个模拟对象,要不然会出现空指针异常

对于原始的那个的哪个方法里面的所有的属性,我们都需要Mock模拟一下,因为你如果不模拟的话,那么测试这个方法执行到这个对象的地方,就会出现空指针异常,因为我们单测的时候,所有的对象都需要用模拟对象,如果你没有用模拟对象,就会出现空指针异常,如下图:

在这里插入图片描述

在单测方法所对应的那个类中,没有引入模拟对象EnvUtils,如下图:

在这里插入图片描述

然后对应的真实方法的地方,牵涉到envUtils对象的地方就会报空指针异常,如下图:

在这里插入图片描述

查看覆盖率

第一步打开mvn,如下图:

在这里插入图片描述

第二步输入mvn命令,如下图:

mvn clean test org.jacoco:jacoco-maven-plugin:0.8.0:prepare-agent install -Dmaven.test.failure.ignore=true

在这里插入图片描述

第三步:执行之后去deploy->target->site->jacoco-resources->index.html查看,在浏览器打开index.html页面,可以查看覆盖率。

在这里插入图片描述

使用jacoco在浏览器查看覆盖率的方法

引入jacoco插件坐标

要想要使用jacoco在线生成覆盖率,首先需要在pom.xml文件中引入jacoco插件,如下图:

在这里插入图片描述

<build>
    <plugins>
        <!-- 单测覆盖率-->
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                </execution>
                <execution>
                    <id>report</id>
                    <phase>test</phase>
                    <goals>
                        <goal>report-aggregate</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <propertyName>surefireArgLine</propertyName>
                <excludes>
                    <exclude>**/model/*</exclude>
                    <exclude>**/model/**</exclude>
                    <exclude>**/dto/*</exclude>
                    <exclude>**/dal/**</exclude>
                    <exclude>**/copy/*</exclude>
                    <exclude>**/util/*</exclude>
                    <exclude>**/utils/**</exclude>
                    <exclude>**/task/**</exclude>
                    <exclude>**/constant/*</exclude>
                    <exclude>**/*Config.class</exclude>
                    <exclude>**/*Util.class</exclude>
                    <exclude>**/*Exception.class</exclude>
                    <exclude>**/*Enum.class</exclude>
                    <exclude>com/timevale/budget/service/mq/MqConsumer.class</exclude>
                    <exclude>com/timevale/budget/service/impl/ExcelServiceImpl.class</exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

把build标签写在denpendencies的下面就行了。

引入mockito的坐标

使用mockito写单测的时候,我们需要先引入mockito的坐标,如下图:

在这里插入图片描述

<!-- 单元测试-->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.6.28</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.11.2</version>
    <scope>test</scope>
</dependency>
在Mockito单元测试的配置文件中对写好的单元测试类进行配置

注意一定要在配置文件中对自己写的单元测试类进行配置,否则的话,在index.html页面看不到我们单元测试类的覆盖率。
在这里插入图片描述

输入maven命令

在maven工具中,输入下面的命令:

mvn clean test org.jacoco:jacoco-maven-plugin:0.8.0:prepare-agent install -Dmaven.test.failure.ignore=true

在这里插入图片描述

结果如下图:

在这里插入图片描述

浏览器打开index.html的效果

在这里插入图片描述

特别注意一个容易出错的点

我这里的工程是buget工程,这个工程存放在我本地的电脑中了,特别注意:存放这个工程的目录不能含有中文,必须要是全英文,要不然的话,在浏览器中打开index.html文件的时候,会显示覆盖率为0。

以后只要是本地电脑存放工程的目录,都必须要是全英文的,防止出现一些奇怪的错误,记住这个规范,如下图:

在这里插入图片描述

通过jacoco生成的单测视图总结打桩规则

单测一个方法的时候,首先去分析这个方法需要使用那些模拟数据,然后在分析有哪几个地方需要进行打桩,我们直接在打桩的时候返回这些模拟数据就行了,如下图:

在这里插入图片描述

在这里插入图片描述

除了打桩when和verify不要使用any()参数匹配器

在这里插入图片描述
在这里插入图片描述

模拟构造器

当我们打桩的时候,构造器会先执行,然后再打桩,所以我们一定要先模拟一下构造器,不让它执行,如下图:
在这里插入图片描述

使用any()参数匹配器不能代替基本类型,只能代替对象类型,否则会报空指针错误

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

原方法中后续如果用不到它的返回值,我们可以不用打桩,可以什么都不用做

在这里插入图片描述
上图中我们就可以把左边的那个打桩给去掉,单元测试仍然能够执行成功。

模拟的类一定要进行close掉

对于我们模拟的类,一定要对它进行close,不管我们模拟的是工具类,还是模拟的其它的什么类,在执行完真实的方法之后,一定都要close一下,否则的话后面再模拟这个类的时候会出错。一定要在执行完真正的业务方法之后再进行close,否则的话,在没有执行真正的业务方法之前进行close方法的调用就相当于是没有模拟。
如下图:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
如果没有close掉模拟的对象,后面的方法再次模拟这个类的时候,会报错,如下图:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/546763.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

语音智能客服机器人有什么优势?ai机器人部署

人工智能技术的进步&#xff0c;在不断的革新我们的工作和生活&#xff0c;同时&#xff0c;拥有人工智能技术的语音智能客服机器人在销售行业的工作熟悉程度也越来越好&#xff0c;那语音智能客服机器人有什么优势&#xff1f;我们一起来看看。 1、ASR语音文本转换 客户可通过…

微服务之分布式链路追踪

一、概述 1.1背景 在微服务框架中&#xff0c;一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果&#xff0c;每一个前段请求都会形成一条复杂的分布式服务调用链路&#xff0c;链路中的任何一环出现高延时或错误都会引起整个请求最…

k8s高可用集群部署介绍 -- 理论

部署官网参考文档 负载均衡参考 官网两种部署模式拓扑图和介绍 介绍两种高可用模式 堆叠 拓扑图如下&#xff08;图片来自k8s官网&#xff09;&#xff1a; 特点&#xff1a;将etcd数据库作为控制平台的一员&#xff0c;由于etcd的共识算法&#xff0c;所以集群最少为3个&…

【算法】快速排序的基本思想、优化 | 挖坑填补法和区间分割法

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法分析与设计知识专栏&#xff1a;算法分析&#x1f525; 给大家跳…

Spire.PDF for .NET【文档操作】演示:合并 PDF 文档

需要合并 PDF 的原因有很多。例如&#xff0c;合并 PDF 文件允许您打印单个文件&#xff0c;而不是为打印机排队多个文档&#xff0c;组合相关文件通过减少要搜索和组织的文件数量来简化管理和存储多个文档的过程。在本文中&#xff0c;您将学习如何使用Spire.PDF for .NET将多…

STM32移植嵌入式开源按键框架

目录 STM32移植嵌入式开源按键框架 MultiButton简介 multi_button.c文件 multi_button.h文件 按键事件 案例使用方法 学习剖析 STM32移植嵌入式开源按键框架 今天移植了一款嵌入式按键框架工程MultiButton&#xff0c;MultiButton是一个小巧简单易用的事件驱动型按键驱动…

OSCP靶场--Wombo

OSCP靶场–Wombo 考点(redis 主从复制RCE ) 1.nmap扫描 ## ┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC 192.168.153.69 -p- -Pn --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-13 07:33 EDT Nmap scan report for 192.168.153.69 Host is u…

代理IP服务商:选择、优势与未来趋势

目录 一、代理IP服务商的选择 二、代理IP的优势 三、代理IP的未来发展趋势 在网络爬虫、数据采集、SEO优化等网络应用中&#xff0c;代理IP扮演着不可或缺的角色。代理IP服务商则是提供这些代理IP资源的主体&#xff0c;如何选择合适的服务商&#xff0c;以及代理IP的优势和…

风速Weibull分布和光伏Beta分布的参数拟合方法(含matlab算例)

在风光场景生成、随机优化调度等研究中&#xff0c;常常假设风速服从Weibull分布&#xff0c;太阳辐照度服从Beta分布。那我们如何得到两个分布的参数呢&#xff1f;文本首先介绍了风速Weibull分布和辐照度Beta分布的基本概率模型及其性性质&#xff0c;之后以MATLAB代码为例阐…

【JAVA基础篇教学】第七篇:Java异常类型说明

博主打算从0-1讲解下java基础教学&#xff0c;今天教学第七篇&#xff1a;Java异常类型说明。 在Java中&#xff0c;错误&#xff08;Error&#xff09;是Throwable类及其子类的实例&#xff0c;它们通常表示严重的问题&#xff0c;无法通过程序来处理&#xff0c;而是需要进…

javaWeb项目-外面点餐系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、Spring Boot框架 …

vue3第十八节(diff算法)

引言&#xff1a; 上一节说了key的用途&#xff0c;而这个key属性&#xff0c;在vue的vnode 中至关重要&#xff0c;直接影响了虚拟DOM的更新机制&#xff1b; 什么场景中会用到diff算法 如&#xff1a;修改响应式属性需要重新渲染页面&#xff0c;会重新执行render渲染函数返…

AndroidStudio 导出aar包,并使用

打包 1、确认当前选项是否勾选&#xff0c;如未勾选请先勾选。 2、勾选完成后重启Android Studio。 3、重启完成后&#xff0c;选中要打包的module 4、打包完成 使用 1.在项目中新建libs,放入aar文件。 2.修改配置 添加如下代码 flatDir {dirs("libs")}3.修改app…

MongoDB 使用

1 引用依赖包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>2 配置文件配置mongodb资料 # MongoDB连接信息 spring.data.mongodb.host 192.168.23.…

ESP32_IDF前端命令开发全过程

ESP32 IDF前端命令开发全过程 开端1. 创建新工程(create-project)2. 创建新组件(create--component)目前文件结构 3. 设置目标芯片4. 配置项目5. 编译工程6. 烧录程序7. 打开监视器8. 一次性编译烧录并打开监视器9. 擦除设备flash10. 查询内存剩余11. 清除编译文件 仅供本人查阅…

【位运算】Leetcode 消失的两个数字

题目解析 面试题 17.19. 消失的两个数字 算法讲解 我们将这两个数组异或在一起&#xff0c;最后的结果就是a ^ b(缺失的两个数字)的结果&#xff0c;这两个缺失的数字一定是不相同的&#xff0c;所以我们就寻找他们第一个比特位是1的那个位置&#xff0c;异或的原理是&#xf…

为了执行SQL语句,MySQL的架构是怎样设计的

1. 把MySQL当个黑盒子一样执行SQL语句 上一讲我们已经说到&#xff0c;我们的系统采用数据库连接池的方式去并发访问数据库&#xff0c;然后数据库自己其实也会维护一个连 接池&#xff0c;其中管理了各种系统跟这台数据库服务器建立的所有连接 我们先看下图回顾一下 当我们的…

WordPress用户福音:Elementor Pro国产版替代方案,全新中文界面更懂你

如果你正在考虑创建自己的网站&#xff0c;那么在第一次谷歌搜索时&#xff0c;你可能已经看到了WordPress、Elementor和网站构建器这些专业名称。WordPress是最受欢迎的网站平台之一&#xff0c;这不难理解&#xff1a;它高度可定制&#xff0c;易于学习&#xff0c;而且是免费…

第十五届蓝桥杯 javaB组第三题

测试通过了90% 剩下10%不知道哪错了 思路&#xff1a;我想的是用map&#xff0c;k存第几个队列&#xff0c;value存每个子队列的长度&#xff0c;最后给value排序 第一个就最小的也就是是有效元素数量 考试只对了个案例&#xff0c;其它情况没测试。 复盘 回来后经过修改改…

3.00 版本来了!DolphinDB V2.00.12 V3.00.0 正式发布!

一文带你了解 DolphinDB 全新版本升级&#xff01; 本次更新后&#xff0c;3.00.0版本将成为 DolphinDB 的最新版&#xff0c;2.00.12版本变更为稳定版&#xff0c;此前发布的1.30.23版本将成为1.30系列的最后一个版本。接下来&#xff0c;带大家一起看看 DolphinDB V2.00.12 …