SonarQube部署及Powermock测试用例编写

1.部署篇

1.1安装流程

  1. 在官网下载SonarQube7.4sonarqube官网
    ps:本来使用的是推荐的最新9.1版本,在启动bin目录下StartSonar.bat出现无法创建jvm的错误,个人判断为java版本与SonarQube版本不符(jdk版本为1.8.144
  2. 新建数据库
create database sonar7 default character set utf8 collate utf8_general_ci;

数据库如果要使用Mysql,要使用5.6/5.7版本,soanr.properties有Mysql和其他数据库兼容版本相关描述
在这里插入图片描述

  1. 修改配置文件
    下载后配置sonar.properties,加入如下配置(mysql配置自己修改)
sonar.jdbc.url=jdbc:mysql:Mysql IP//Mysql port:/sonar7?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false  
sonar.jdbc.username=root #数据库用户名 
sonar.jdbc.password=root #数据库密码
sonar.sorceEncoding=UTF-8
sonar.login=admin #web页面注册的账号
sonar.password=admin #web页面注册的密码
  1. 点击bin目录下StartSonar.bat即可运行,初次启动较慢,因为要初始化数据库,由于本人使用的阿里云服务器,且已经安装了8.0版本Mysql,所以使用Docker部署5.7版本的数据库,映射到8090端口,由于网络传输和容器的影响,构建较慢,大概20-30分钟,耐心等待
  2. 等待snoar up后,打开http://localhost:9000(也可以提前打开,不过必须等待sonar up后才可以显示相关数据)

1.2 关闭流程

首先关闭StartSonar.bat启动后出现的命令行界面
其次打开任务管理器关闭三个Java进程
在这里插入图片描述
ps:之前在启动StartSonar.bat时,一直报该异常

2021.10.17 02:52:33 WARN app[][o.e.t.n.Netty4Transport] exception caught on transport layer [[id: 0xe49808db, L:/127.0.0.1:1623 - R:/127.0.0.1:9001]], closing connection
java.io.IOException: 远程主机强迫关闭了一个现有的连接。
at sun.nio.ch.SocketDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:43)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
at sun.nio.ch.IOUtil.read(IOUtil.java:192)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:380)
at io.netty.buffer.UnpooledUnsafeDirectByteBuf.setBytes(UnpooledUnsafeDirectByteBuf.java:433)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1100)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:372)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:123)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:644)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:579)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:496)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:458)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
at java.lang.Thread.run(Thread.java:748)

. 查询logs下日志发现端口被占用,也懒得查了,直接重启电脑,启动成功

1.3汉化插件安装

在sonar的market搜索chinese,点击install,报错,不兼容,去github下载对应版本的插件 ,放到
sonarqube-7.4\extensions\plugins目录下
https://github.com/xuhuisheng/sonar-l10n-zh
该页面提供了sonarqube和汉化插件的对应版本,根据自己的sonarqube版本去下载对应版本的汉化插件即可

2.PowerMock使用篇

前置概念以及注意事项

  • Mock和new出来的对象,对Mock对象set属性是无法成功set的,而new出来的对象可以set属性

  • doReturn().when()和when().return()区别,前者不会执行代码,后者会执行代码,如代码有异常,后者会出现问题,而前者不会(推荐使用前者),两种模式都用于模拟对象方法,在mock实例下使用时,基本上是没有差别的。但是,在spy实例下使用时,when().thenReturn()模式会执行原方法,而doReturn().when()模式不会执行原方法。

  • 如果被测方法的参数有boolean类型,那么在stubbing时该参数要使用anyBoolean(),不能使用any(),会报空指针异常

  • @Autowired注入的属性,使用@Mock配置时,mock出的变量名必须相同(如subService),必须和被测试代码中@Autowried注入的SubService同名(subService),否则会报非法参数异常(IllegalArgumentException)

java.lang.IllegalArgumentException: Could not find field ‘productRepository’ of type [null] on target object

@RunWith(PowerMockRunner.class)
@PrepareForTest({xxxServiceImpl.class})
public class xxxServiceImplTest {
    @InjectMocks
    private xxxServiceImpl xxxService;
    @Mock
    private SubService subService;
    
    @Before
    public void setUp() {
        xxxService = PowerMockito.spy(new xxxServiceImpl());
        ReflectionTestUtils.setField(xxxService, "subService", subService);
        }
       @Test
       public void methodTest(){
       }

tips:
//静态导包,使用assertEquals()简化Assert.assertEquals(),使用any()简化Mockito.any()
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

2.1Controller层测试案例

@RunWith(PowerMockRunner.class)
@PrepareForTest({xxxController.class})
public class xxxControllerTest {
    @InjectMocks
    private xxxController xxxController;
    @Mock
    private xxxServiceImpl xxxService;
    @Mock
    private yyyService yyyService;
    @Before
    public void setUp() {
        // mock私有方法
        xxxController = PowerMockito.spy(new xxxController());
        ReflectionTestUtils.setField(xxxController, "xxxService", xxxService);
        ReflectionTestUtils.setField(xxxController, "yyyService", yyyService);
    }
    @Test
    public void method1() {
       //模拟被测方法的返回值
       ResponseResult  result = xxxController.method1(arg1,arg2);
       。。。
       //以下按情况选择
       assertNull(result.getData());
       assertNotNull(result.getData());
       assertEquals("targetValue",result.getData());
    }
}

2.2service层测试案例

@RunWith(PowerMockRunner.class)
@PrepareForTest(xxxServiceImpl.class})
public class xxxServiceImplTest {
    @InjectMocks
    private xxxServiceImpl xxxService;
    @Mock
    private yyyyService yyyService;
    @Mock
    private zzzRepository zzzRepository;
   


    @Before
    public void setUp() {
        xxxService = PowerMockito.spy(new xxxServiceImpl());
        ReflectionTestUtils.setField(xxxService, "yyyService", yyyService);
        ReflectionTestUtils.setField(xxxOrderService, "zzzRepository", zzzRepository);
     
    }

    @Test
    public void method1() {
        
    	//根据被测方法是否有返回值选择
		//1.无返回值
    	PowerMockito.doNothing().when(xxxService).method1(Mockito.any(param1.class), Mockito.any(param2.class));
    	//构造参数执行被测方法
    	...
		Mockito.verify(xxxService, Mockito.times(1)).method(param1, param2);
		//2.有返回值
    	PowerMockito.doReturn(expected result).when(xxxService).method2(Mockito.any(param1.class), Mockito.any(param2.class));
    	//构造参数执行被测方法
    	...
       assertNull();
       assertNotNull();
       assertEquals();
       }
}

2.3Dao层(Repository层)测试案例

2.4异常测试案例

2.4.1@Test(expectd = Exception.class)注解形式
@Test(expected= MyException.class)
public String  myMethod{
}
2.4.2Assert.assertThrows()
Assert.assertThrows(BusinessException.class, () -> {
            xxxService.method(par1,par2);
        });

2.5void返回值测试案例

使用verify()方法测试代码调用方法是否执行,是否是预期的执行次数

Mockito.verify(xxxService, Mockito.times(1)).method(any(), any(), any());

2.6使用MybatisPlus的Lambda表达式测试案例

被测代码

List<Product> list = productRepository.lambdaQuery()
                .eq(Product::getProdutType, productType)
                .eq(Product::getDelFlag, delFlag)
                .list();

测试代码

LambdaQueryChainWrapper lambdaQueryChainWrapper = PowerMockito.mock(LambdaQueryChainWrapper.class);
        PowerMockito.doReturn(lambdaQueryChainWrapper).when(xxxRepository).lambdaQuery();
        PowerMockito.doReturn(lambdaQueryChainWrapper).when(lambdaQueryChainWrapper).eq(any(), any());
        PowerMockito.doReturn(list).when(lambdaQueryChainWrapper).list();

2.7PowerMock模拟private方法(method()和invoke()方法)

         Method method = PowerMockito.method(xxxRepositoryImpl.class, "method1",Param.class);

        Result result=(Result) method.invoke(xxxRepository,param);

3.参考链接

参考:
https://mp.weixin.qq.com/s/LSkTvpsTnBmdOB5nihkxng
https://www.jianshu.com/p/4d9d2534c0d3

待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值