mockito加junit实现单元测试笔记

目录

    • 一、简介
      • 1.1 单元测试的特点
      • 1.2 mock类框架使用场景
      • 1.3 常用mock类框架
        • 1.3.1 mockito
        • 1.3.2 easymock
        • 1.3.3 powermock
        • 1.3.4 JMockit
    • 二、mockito的单独使用
      • 2.1 mock对象与spy对象
      • 2.2 初始化mock/spy对象的方式
        • 初始化mock/spy对象第1种方式
        • 初始化mock/spy对象第2种方式
        • 初始化mock/spy对象第3种方式
      • 2.3 参数匹配
      • 2.4 方法插桩
        • 返回指定值
        • void返回值方法插桩
        • 插桩的两种方式
        • 抛异常
        • 多次插桩
        • thenAnswer
        • 执行真正的原始方法
        • verify的使用
      • 2.5 @InjectMocks注解的使用
      • 断言工具
    • 三、实战讲解
    • 四、mockito在springboot环境使用(不推荐)
    • 附上其他代码

此文根据视频《mockito加junit搞定单元测试》进行整理,如有侵权,联系删除。

一、简介

1.1 单元测试的特点

  • 配合断言使用(杜绝System.out) 。
  • 可重复执行 。
  • 不依赖环境 。
  • 不会对数据产生影响。
  • spring的上下文环境不是必须的 。
  • 一般都需要配合mock类框架来实现。

1.2 mock类框架使用场景

要进行测试的方法存在外部依赖(如db,redis,第三方接口调用等),为了能够专注于对该方法(单元)的逻辑进行测试,就希望能虚拟出外部依赖,避免外部依赖成为测试的阻塞项。
用到mock类框架进行虚拟这些外部依赖。
一般单元测试都是针对service层。

1.3 常用mock类框架

mock类框架:用于mock外部依赖

1.3.1 mockito

名称:ito:input to output
官网:https://site.mockito.org
官网文档:https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html
限制:老版本对于final class、final method、static method、private method 均不能被 mockito mock。目前已支持final class、final method、static method 的 mock,具体可以参考官网
(39. Mocking final types, enums and final methods (Since 2.1.0))
(48. New API for mocking static methods (Since 3.4.0))

原理:bytebuddy 教程:https://www.bilibili.com/video/BV1G24y1a7bd
(通过修改字节码来实现代理的)

1.3.2 easymock
1.3.3 powermock

官网:https://github.com/powermock/powermock
与 mockito 的版本支持关系:https://gitee.com/mirrors/powermock/wikis/Mockito#supported-versions
对 mockito 或 easymock 的增强

1.3.4 JMockit

二、mockito的单独使用

2.1 mock对象与spy对象

方法插桩方法不插桩作用对象最佳实践
mock对象执行插桩逻辑返回mock对象的默认值(0 / null / 空集合)类、接口被测试类或其依赖
spy对象执行插桩逻辑调用真实方法类、接口被测试类

使用 mockingDetails 判断对象是否为 mock对象、spy 对象

2.2 初始化mock/spy对象的方式

方法一方法二方法三
junit4@RunWith(MockitoJUnitRunner.class) +@Mock等注解Mockito.mock(X.class)等静态方法MockitoAnnotations.openMocks(this)+@Mock等注解
junit5@ExtendWith(MockitoExtension.class) + @Mock等注解Mockito.mock(X.class)等静态方法MockitoAnnotations.openMocks(this)+@Mock等注解
初始化mock/spy对象第1种方式
/**
 * 初始化mock/spy对象有3种方式,第1种方式
 */
@RunWith(MockitoJUnitRunner.class)
public class InitMockOrSpyMethod1Test {
    @Mock
    private UserService mockUserService;
    @Spy
    private UserService spyUserService;

    @Test
    public void test1() {
        // true
        System.out.println("Mockito.mockingDetails(mockUserService).isMock() = " + Mockito.mockingDetails(mockUserService).isMock());
        // false
        System.out.println("Mockito.mockingDetails(mockUserService).isSpy() = " + Mockito.mockingDetails(mockUserService).isSpy());
        // true
        System.out.println("Mockito.mockingDetails(spyUserService).isMock() = " + Mockito.mockingDetails(spyUserService).isMock());
        // true
        System.out.println("Mockito.mockingDetails(spyUserService).isSpy() = " + Mockito.mockingDetails(spyUserService).isSpy());
    }
}
初始化mock/spy对象第2种方式
/**
 * 初始化mock/spy对象有3种方式,第2种方式
 */
public class InitMockOrSpyMethod2Test {
    private UserService mockUserService;
    private UserService spyUserService;

    @Before
    public void init() {
        mockUserService = Mockito.mock(UserService.class);
        spyUserService = Mockito.spy(UserService.class);
    }

    @Test
    public void test1() {
        // true
        System.out.println("Mockito.mockingDetails(mockUserService).isMock() = " + Mockito.mockingDetails(mockUserService).isMock());
        // false
        System.out.println("Mockito.mockingDetails(mockUserService).isSpy() = " + Mockito.mockingDetails(mockUserService).isSpy());
        // true
        System.out.println("Mockito.mockingDetails(spyUserService).isMock() = " + Mockito.mockingDetails(spyUserService).isMock());
        // true
        System.out.println("Mockito.mockingDetails(spyUserService).isSpy() = " + Mockito.mockingDetails(spyUserService).isSpy());
    }
}
初始化mock/spy对象第3种方式
/**
 * 初始化mock/spy对象有3种方式,第3种方式
 */
public class InitMockOrSpyMethod3Test {
    @Mock
    private UserService mockUserService;
    @Spy
    private UserService spyUserService;

    @Before
    public void init() {
//        MockitoAnnotations.initMocks(this);
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void test1() {
        // true
        System.out.println("Mockito.mockingDetails(mockUserService).isMock() = " + Mockito.mockingDetails(mockUserService).isMock());
        // false
        System.out.println("Mockito.mockingDetails(mockUserService).isSpy() = " + Mockito.mockingDetails(mockUserService).isSpy());
        // true
        System.out.println("Mockito.mockingDetails(spyUserService).isMock() = " + Mockito.mockingDetails(spyUserService).isMock());
        // true
        System.out.println("Mockito.mockingDetails(spyUserService).isSpy() = " + Mockito.mockingDetails(spyUserService).isSpy());
    }
}

2.3 参数匹配

/**
 * 参数匹配:通过方法签名(参数)来指定哪些方法调用需要被处理(插桩、verify验证)
 */
@RunWith(MockitoJUnitRunner.class)
public class ParamMatcherTest {
    @Mock
    private UserService mockUserService;

    /**
     * 对于mock对象,不会调用真实方法,直接返回mock对象的默认值
     * 默认值:0(int)、null、空集合
     */
    @Test
    public void test1() {
        UserVO userVO = mockUserService.selectById(1L);
//        userVO = null
        System.out.println("userVO = " + userVO);
        UserUpdateReq userUpdateReq = new UserUpdateReq();
        int i = mockUserService.modifyById(userUpdateReq);
//        i = 0
        System.out.println("i = " + i);
    }

    /**
     * 测试插桩时的参数匹配,只拦截userUpdateReq1
     */
    @Test
    public void test2() {
        UserUpdateReq userUpdateReq1 = new UserUpdateReq();
        userUpdateReq1.setId(1L);
        userUpdateReq1.setPhone("1");
        Mockito.doReturn(99).when(mockUserService).modifyById(userUpdateReq1);

        int result1 = mockUserService.modifyById(userUpdateReq1);
        // result1 = 99
        System.out.println("result1 = " + result1);

        UserUpdateReq userUpdateReq2 = new UserUpdateReq();
        userUpdateReq2.setId(2L);
        userUpdateReq2.setPhone("2");
        int result2 = mockUserService.modifyById(userUpdateReq2);
        // result2 = 0
        System.out.println("result2 = " + result2);

        int result3 = mockUserService.modifyById(userUpdateReq1);
        // result3 = 99
        System.out.println("result3 = " + result3);
    }

    /**
     * 测试插桩时的参数匹配,ArgumentMatchers.any(UserUpdateReq.class)拦截UserUpdateReq类型的任意对象
     * 除了ArgumentMatchers.any(XXX.class),还有anyXXX(),例如anyString(),anyLong()...
     */
    @Test
    public void test3() {
        Mockito.doReturn(99).when(mockUserService).modifyById(ArgumentMatchers.any(UserUpdateReq.class));

        UserUpdateReq userUpdateReq1 = new UserUpdateReq();
        userUpdateReq1.setId(1L);
        userUpdateReq1.setPhone("1");
        Mockito.doReturn(99).when(mockUserService).modifyById(userUpdateReq1);
        int result1 = mockUserService.modifyById(userUpdateReq1);
        // result1 = 99
        System.out.println("result1 = " + result1);

        UserUpdateReq userUpdateReq2 = new UserUpdateReq();
        userUpdateReq2.setId(2L);
        userUpdateReq2.setPhone("2");
        int result2 = mockUserService.modifyById(userUpdateReq2);
        // result2 = 99
        System.out.println("result2 = " + result2);

        int result3 = mockUserService.modifyById(userUpdateReq1);
        // result3 = 99
        System.out.println("result3 = " + result3);
    }

    /**
     * 测试插桩时的参数匹配,除了ArgumentMatchers.any(XXX.class),还有anyXXX(),例如anyString(),anyLong()...
     * 注意:anyXXX()不包括null
     */
    @Test
    public void test4() {
        List<String> featureList = new ArrayList<>();
        featureList.add("高");
        featureList.add("富");

        mockUserService.add("zhangsan", "123", featureList);
        mockUserService.add("wangwu", "789", featureList);
//        mockUserService.add("zhangsan", "456", null);

        Mockito.verify(mockUserService, Mockito.times(1)).add("zhangsan", "123", featureList);
        Mockito.verify(mockUserService, Mockito.never()).add("lisi", "123", featureList);
        Mockito.verify(mockUserService, Mockito.times(2)).add(ArgumentMatchers.anyString(), ArgumentMatchers.anyString(), ArgumentMatchers.anyList());
//        不允许部分使用anyXXX表达式
//        Mockito.verify(mockUserService, Mockito.times(2)).add(ArgumentMatchers.anyString(), "123", featureList);
    }
}

2.4 方法插桩

指定调用某个方法时的行为(stubbing),达到相互隔离的目的

返回指定值
void返回值方法插桩
插桩的两种方式
  • when(obj.someMethod()).thenXxx():其中obj可以是mock对象
  • doXxx().when(obj).someMethod():其中obj可以是mock/spy对象或对无返回值的方法进行插桩
抛异常
多次插桩
thenAnswer
执行真正的原始方法
verify的使用
@RunWith(MockitoJUnitRunner.class)
public class StubTest {
    @Mock
    private List<String> mockList;
    @Mock
    private UserServiceImpl mockUserServiceImpl;
    @Spy
    private UserServiceImpl spyUserServiceImpl;

    /**
     * 指定返回值
     */
    @Test
    public void testReturn() {
        // 方法1
        Mockito.doReturn("zero").when(mockList).get(0);
        Assert.assertEquals("zero", mockList.get(0));

        // 方法2
        Mockito.when(mockList.get(1)).thenReturn("one");
        Assert.assertEquals("one", mockList.get(1));
    }

    /**
     * void返回值方法插桩
     */
    @Test
    public void testVoid() {
        // 调用mockList.clear时候什么都不做
        Mockito.doNothing().when(mockList).clear();
        mockList.clear();
        // 验证调用了一次clear
        Mockito.verify(mockList, Mockito.times(1)).clear();
    }

    /**
     * 插桩的两种方式
     */
    @Test
    public void testReturnMethod() {
        Mockito.when(mockUserServiceImpl.getNumber()).thenReturn(99);
        // 99
        System.out.println("mockUserServiceImpl.getNumber() = " + mockUserServiceImpl.getNumber());

        Mockito.when(spyUserServiceImpl.getNumber()).thenReturn(99);
        // 会打印getNumber
        // 再打印99
        // spy对象在没有插桩时候是调用真实方法的,写在when中会导致先执行一次原方法,达不到mock的目的
        System.out.println("spyUserServiceImpl.getNumber() = " + spyUserServiceImpl.getNumber());

        Mockito.doReturn(999).when(spyUserServiceImpl).getNumber();
        // 99
        System.out.println("spyUserServiceImpl.getNumber() = " + spyUserServiceImpl.getNumber());
    }

    /**
     * 抛出异常
     */
    @Test
    public void testThrowException() {
        // 方法有返回值
        Mockito.when(mockList.get(ArgumentMatchers.anyInt())).thenThrow(RuntimeException.class);
//        Mockito.doThrow(RuntimeException.class).when(mockList).get(ArgumentMatchers.anyInt());
        try {
            mockList.get(4);
            Assert.fail();
        } catch (Exception e) {
            Assert.assertTrue(e instanceof RuntimeException);
        }

        // 方法没返回值
        Mockito.doThrow(RuntimeException.class).when(mockList).clear();
        try {
            mockList.clear();
            Assert.fail();
        } catch (Exception e) {
            Assert.assertTrue(e instanceof RuntimeException);
        }
    }

    /**
     * 多次插桩
     */
    @Test
    public void testMultipleStub() {
        Mockito.when(mockList.size()).thenReturn(1).thenReturn(2).thenReturn(3);
//        Mockito.when(mockList.size()).thenReturn(1, 2, 3);
        Assert.assertEquals(1, mockList.size());
        Assert.assertEquals(2, mockList.size());
        Assert.assertEquals(3, mockList.size());
        Assert.assertEquals(3, mockList.size());
    }

    /**
     * 指定实现逻辑的插桩
     * thenAnswer可以实现对方法进行插桩,以实现自定义返回值逻辑。我们只需实现函数式接口Answer,并实现自定义返回值逻辑即可。
     * 泛型表示要插桩方法的返回值类型,此处我们使用String
     */
    @Test
    public void testThenAnswer() {
        Mockito.when(mockList.get(ArgumentMatchers.anyInt())).thenAnswer(new Answer<String>() {
            @Override
            public String answer(InvocationOnMock invocationOnMock) throws Throwable {
                Integer argument = invocationOnMock.getArgument(0, Integer.class);
                return String.valueOf(argument * 100);
            }
        });
        String result = mockList.get(3);
        Assert.assertEquals("300", result);
    }

    /**
     * 执行真正的原始方法
     */
    @Test
    public void testCallRealMethod() {
        // 对mock对象插桩让它执行原始方法
        Mockito.when(mockUserServiceImpl.getNumber()).thenCallRealMethod();
        int mockResult = mockUserServiceImpl.getNumber();
        Assert.assertEquals(100, mockResult);

        // 不对spy对象插桩,spy对象默认就会调用真实方法
        int spyResult = spyUserServiceImpl.getNumber();
        Assert.assertEquals(100, spyResult);
        // 如果不想spy对象调用真实方法,则需要对它进行插桩
        Mockito.doReturn(999).when(spyUserServiceImpl).getNumber();
        spyResult = spyUserServiceImpl.getNumber();
        Assert.assertEquals(999, spyResult);
    }

    /**
     * 测试verify
     */
    @Test
    public void testVerify() {
        mockList.add("one");
        mockList.add("two");
        mockList.clear();

        Mockito.verify(mockList).add("one");

        Mockito.verify(mockList, Mockito.times(1)).add("one");
        Mockito.verify(mockList, Mockito.times(2)).add(ArgumentMatchers.anyString());

        Mockito.verify(mockList, Mockito.never()).size();
        Mockito.verify(mockList, Mockito.times(0)).size();
    }
}

2.5 @InjectMocks注解的使用

  • 作用:若此注解声明的变量需要用到mock/spy对象, mockito会自动使用当前类里的mock或spy成员进行按类型或名字的注入。
  • 原理:构造器注入、setter注入、字段反射注入
@RunWith(MockitoJUnitRunner.class)
public class InjectMocksTest {
    // 执行test1方法报错,因为被@InjectMocks注解标注的类必须是实现类,mockito会创建对应的实例对象
//    @InjectMocks
//    private UserService userService;

    // 默认创建的对象就是未经过mockito处理的普通对象
//    @InjectMocks
//    private UserServiceImpl userService;

//    配合@Spy注解使其变成默认调用真实方法的对象
    @InjectMocks
    @Spy
    private UserServiceImpl userService;

//    使用@Mock注解注入到@InjectMocks注解对应的实例对象中
//    如果不使用@Mock注解注入userFeatureService到userService中,执行test1方法过程中,userFeatureService是null
    @Mock
    private UserFeatureService userFeatureService;

    @Test
    public void test1() {
        int number = userService.getNumber();
        Assert.assertEquals(100, number);
    }
}

断言工具

hamcrest:junit4中引入的第三方断言库,junit5中被移出,从1.3版本后,坐标由org.hamcrest:hamcrest-core变为org.hamcrest:hamcrest,用的少
assertj:常用的断言库
junit4原生断言
junit5原生断言

三、实战讲解

四、mockito在springboot环境使用(不推荐)

生成的对象受spring管理
@MockBean

  • 类似@Mock
  • 用于通过类型或名字替换spring容器中已经存在的bean,从而达到对这些bean进行mock的目的

@SpyBean

  • 作用类似@Spy
  • 用于通过类型或名字包装spring容器中已经存在的bean,当需要mock被测试类的某些方法时可以使用

附上其他代码

create database mockito_demo CHARACTER SET utf8mb4;
use mockito_demo;
 
drop table if exists user;
CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT comment '主键',
  `username` varchar(100) NOT NULL comment '用户名称',
  `phone` varchar(50) NOT NULL comment '电话',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB comment '用户表';
 
drop table if exists user_feature;
CREATE TABLE `user_feature` (
  `id` bigint NOT NULL AUTO_INCREMENT comment '主键',
  `user_id` bigint NOT NULL comment '用户id:用户表的主键',
  `feature_value` varchar(150) NOT NULL comment '用户的特征值',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB comment '用户特征表';
 
insert into user(username, phone) values('xiaoming','12345678912');
insert into user_feature(user_id,feature_value) values(1,'abc');
insert into user_feature(user_id,feature_value) values(1,'def');
insert into user_feature(user_id,feature_value) values(1,'ghi');
@SpringBootApplication
@EnableTransactionManagement
@MapperScan("com.lm.mockito.mapper")
public class MockitoApp {
    public static void main(String[] args) {
        SpringApplication.run(MockitoApp.class);
    }
}
@RestController
@Validated
public class UserController {
    @Resource
    private UserService userService;

    @GetMapping("/selectById")
    public UserVO selectById(@NotNull Long userId) {
        return userService.selectById(userId);
    }

    @PostMapping("/add")
    public String add(@RequestBody @Validated UserAddReq addReq) {
        userService.add(addReq.getUserName(), addReq.getPhone(), addReq.getFeatureValueList());
        return "OK";
    }
}
public interface UserService extends IService<UserDO> {
    UserVO selectById(Long userId);

    void add(String userName, String phone, List<String> featureValueList);

    int modifyById(UserUpdateReq userUpdateReq);

    int getNumber();
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements UserService {
    @Resource
    private UserFeatureService userFeatureService;

    @Override
    public UserVO selectById(Long userId) {
        UserDO existedEntity = getById(userId);
        if (existedEntity == null) {
            return null;
        }

        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(existedEntity, userVO);

        List<UserFeatureDO> featureList = userFeatureService.selectByUserId(userId);
        if (CollectionUtils.isEmpty(featureList)) {
            return userVO;
        }

        userVO.setFeatureValueList(featureList.stream().map(UserFeatureDO::getFeatureValue).collect(Collectors.toList()));
        return userVO;
    }

    @Override
    public void add(String userName, String phone, List<String> featureValueList) {
        UserDO userDO = new UserDO();
        userDO.setUserName(userName);
        userDO.setPhone(phone);
        save(userDO);

        List<UserFeatureDO> userFeatureDOList = featureValueList.stream().map(featureValue -> {
            UserFeatureDO userFeatureDO = new UserFeatureDO();
            userFeatureDO.setUserId(userDO.getId());
            userFeatureDO.setFeatureValue(featureValue);
            return userFeatureDO;
        }).collect(Collectors.toList());
        userFeatureService.saveBatch(userFeatureDOList);
    }

    @Override
    public int modifyById(UserUpdateReq userUpdateReq) {
        UserDO userDO = new UserDO();
        userDO.setId(userUpdateReq.getId());
        userDO.setUserName(userUpdateReq.getUserName());
        userDO.setPhone(userUpdateReq.getPhone());
        boolean successFlag = updateById(userDO);

        return successFlag ? 1 : -1;
    }

    @Override
    public int getNumber() {
        System.out.println("getNumber");
        return 100;
    }
}
public interface UserFeatureService extends IService<UserFeatureDO> {
    List<UserFeatureDO> selectByUserId(Long userId);
}
@Service
public class UserFeatureServiceImpl extends ServiceImpl<UserFeatureMapper, UserFeatureDO> implements UserFeatureService {
    @Override
    public List<UserFeatureDO> selectByUserId(Long userId) {
        if (Objects.isNull(userId)) {
            return null;
        }
        LambdaQueryWrapper<UserFeatureDO> lqw = Wrappers.<UserFeatureDO>lambdaQuery().eq(UserFeatureDO::getUserId,
                userId);
        return list(lqw);
    }
}
public interface UserMapper extends BaseMapper<UserDO> {
}
public interface UserFeatureMapper extends BaseMapper<UserFeatureDO> {
}
@Data
public class UserAddReq {
    @NotBlank
    private String userName;

    @NotBlank
    private String phone;

    @NotEmpty
    private List<String> featureValueList;
}
@Data
public class UserUpdateReq {
    @NotNull
    private Long id;

    @NotBlank
    private String userName;

    @NotBlank
    private String phone;
}
@Data
public class UserVO {
    private Long id;

    private String userName;

    private String phone;

    private List<String> featureValueList;
}
@Data
@TableName("user")
public class UserDO {
    @TableId(type = IdType.AUTO)
    private Long id;

    private String userName;

    private String phone;
}
@Data
@TableName("user_feature")
public class UserFeatureDO {
    @TableId(type = IdType.AUTO)
    private Long id;

    private Long userId;

    private String featureValue;
}

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

真要mock私有方法,使用powermock

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

数据“表”的增删改查

创建数据表 删除数据表 修改数据表 查看数据表 喜欢点赞收藏&#xff0c;如有疑问&#xff0c;点击链接加入群聊【信创技术交流群】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kEjDhISXNgJlMMemn85viUFgIqzkDY3OC&authKey2SKLwlmvTpbqlaQtJ%2FtFXJgHVgl…

全球与中国HDPE管道市场:增长趋势、竞争格局与前景展望

快速成长的人口、快速的经济成长和工业发展增加了对可靠供水系统的需求。工业需要为制造流程、冷却系统和卫生目的提供可靠的水供应。随着国家的发展&#xff0c;它们更加重视基础设施&#xff0c;包括供水系统&#xff0c;以支持工业成长。HDPE管道广泛应用于饮用水和灌溉的配…

LeetCode 1038. 从二叉搜索树到更大和树:(反)中序遍历

【LetMeFly】1038.从二叉搜索树到更大和树&#xff1a;&#xff08;反&#xff09;中序遍历 力扣题目链接&#xff1a;https://leetcode.cn/problems/binary-search-tree-to-greater-sum-tree/ 给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于…

虹科技术 | BabyLIN产品如何轻松搞定K线协议实现?

概述&#xff1a;为了实现K线通信&#xff0c;SDF-V3在协议部分中定义了新的协议类型KLine Raw。所有能够运行SDF-V3文件&#xff08;LinWorks版本在V.2.29.4以上&#xff09;并使用最新的固件&#xff08;固件版本在V.6.18以上&#xff09;的BabyLIN设备都可以执行KLine Raw协…

【23-24 秋学期】NNDL 作业12 优化算法2D可视化

简要介绍图中的优化算法&#xff0c;编程实现并2D可视化 1. 被优化函数 2. 被优化函数 3. 分析各个算法的优缺点 REF&#xff1a;图灵社区-图书 (ituring.com.cn) 深度学习入门&#xff1a;基于Python的理论与实现 NNDL 作业11&#xff1a;优化算法比较_"ptimizers[…

MYSQL报错 [ERROR] InnoDB: Unable to create temporary file; errno: 0

起因 服务器的mysql不支持远程访问&#xff0c;在修改完相关配置后重启服务出错。 2023-12-03T10:12:23.895459Z 0 [Note] C:\Program Files\MySQL\MySQL Server 5.7\bin\mysqld.exe (mysqld 5.7.22-log) starting as process 15684 ... 2023-12-03T10:12:23.908886Z 0 [Note…

YOLOv8独家原创改进:创新自研CPMS注意力,多尺度通道注意力具+多尺度深度可分离卷积空间注意力,全面升级CBAM

💡💡💡本文自研创新改进:自研CPMS, 多尺度通道注意力具+多尺度深度可分离卷积空间注意力,全面升级CBAM 1)作为注意力CPMS使用; 推荐指数:五星 CPMS | 亲测在多个数据集能够实现涨点,对标CBAM。 收录 YOLOv8原创自研 https://blog.csdn.net/m0_63774211/ca…

内存是如何工作的

一、什么是内存 从外观上辨识&#xff0c;它就是内存条&#xff1b;从硬件上讲&#xff0c;它叫RAM&#xff0c;翻译过来叫随机存储器。英文全称&#xff1a;Random Access Memory。它也叫主存&#xff0c;是与CPU直接交换数据的内部存储器。其特点是读写速度快&#xff0c;不…

一文搞懂系列——动态库的加载方式及应用场景

引文 我们在工作中经常会遇到动态库链接的问题&#xff0c;因为正常的方式并不能满足我们的场景。常见的问题可以总结如下&#xff1a; 系统路径默认路径、usr/lib、/lib 目录&#xff0c;不会集成第三方动态库。 同名动态库可能在多个路径中存在。 针对不同的场景&#xff0…

替代AMS1117-ADJ可调输出线性稳压器(LDO)

1、概 述 PC1117-ADJ/1.2/1.5/1.8/2.5/2.85/3.3/5是最大输出电流为1A的低压降正向稳压器&#xff0c;其中 PC1117-ADJ是可调输出电压版&#xff0c;只需要两个外接电阻即可实现输出电压在1.25V~13.8V范围内的调节&#xff0c;而PC1117-1.2/1.5/1.8/2.5/2.85/3.3/5是固定输出1.…

【陈老板赠书活动 - 19期】-2023年以就业为目的学习Java还有必要吗?

陈老老老板&#x1f9b8; &#x1f468;‍&#x1f4bb;本文专栏&#xff1a;赠书活动专栏&#xff08;为大家争取的福利&#xff0c;免费送书&#xff09; &#x1f468;‍&#x1f4bb;本文简述&#xff1a;生活就像海洋,只有意志坚强的人,才能到达彼岸。 &#x1f468;‍&am…

vector向量详解,小白快速入门

1.vector是什么 vector名为向量&#xff0c;其实就是一个长度可变的数组 是连续的顺序的储存结构&#xff08;和数组一样的类别&#xff09;&#xff0c;但是有长度可变的特性。 2.vector的初始化 vector<int> v; 一维可变数组&#xff0c;类型为int&#xff0c;名称…

xampp环境安装

XAMPP是完全免费且易于安装的Apache发行版&#xff0c;其中包含Apache、MariaDB、PHP和Perl。 类似XAMPP的服务器套件还有很多&#xff0c;我用过的还有UPUPW&#xff0c;它们都极大的简化了开发环境的配置。 下载链接Download XAMPP 我选的最新的 一路next就安装好了。

Cesium 太阳光晕

Cesium 太阳光晕 基于后处理实现位置动态跟随太阳实际位置可以动态改变颜色 viewer.camera.flyTo({destination: { "x": -2471386.549378386, "y": 4838798.836366257, "z": 3329936.5717575867 },duration: 0,orientation: {heading: Cesium.M…

蓝桥杯真题:分巧克力(二分法)

由题目可知,该题的最终结果具有单调性,边长越大,可分蛋糕越少 可以用二分模板的向右找: 整数二分 import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader;public class Main {static int n,k; //n个块蛋糕,k个学生static int N 10…

【开源】基于Vue.js的人事管理系统

文末获取源码&#xff0c;项目编号&#xff1a; S 079 。 \color{red}{文末获取源码&#xff0c;项目编号&#xff1a;S079。} 文末获取源码&#xff0c;项目编号&#xff1a;S079。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 管理员功能模块2.2 普通员工功能模块…

【网络安全】虚假IP地址攻击如何防范?

在当今的网络时代&#xff0c;虚假IP地址攻击已成为一种新型的网络攻击方式&#xff0c;给网络安全带来了极大的威胁。那么&#xff0c;什么是虚假IP地址攻击&#xff1f;又如何进行溯源和防范呢&#xff1f;本文将为您揭开这一神秘面纱。 一、虚假IP地址攻击概述 虚假IP地址攻…

ISP算法简述-BLC

Black Level Calibration, 黑电平矫正 现象 1)在纯黑条件下拍张图&#xff0c;你会发现像素值不为0 2)或者你发现图像整体偏色 这些问题可能是黑电平导致的。 原因 存在黑电平的原因有2个&#xff1a; 1)sensor的电路本身存在暗电流。暗电流主要产生在光电信号转换过程中&#…

quickapp_快应用_生命周期

生命周期 APP的生命周期页面组件的生命周期页面栈页面的生命周期onBackPressonMenuPress踩坑 onRefreshonConfigurationChanged页面滚动 自定义组件的生命周期父子组件初始化生命周期执行顺序 APP的生命周期 App的生命周期在app.ux 中定义的回调函数。 onCreate() {prompt.sh…

Apache solr XXE 漏洞(CVE-2017-12629)

任务一&#xff1a; 复现环境中的漏洞 任务二&#xff1a; 利用XXE漏洞发送HTTP请求&#xff0c;在VPS服务器端接受请求&#xff0c;或收到DNS记录 任务三&#xff1a; 利用XXE漏洞读取本地的/etc/passwd文件 1.搭建环境 2.开始看wp的时候没有看懂为什么是core&#xff0c;然…