首页 > 其他分享 >单元测试(三)

单元测试(三)

时间:2023-07-09 19:22:21浏览次数:32  
标签:单元测试 junit example User import org class

本篇主要介绍PowerMock + Spring + Mybatis + H2单元测试,接上篇:https://www.cnblogs.com/javaXRG/p/17538157.html

1 PowerMock

1.1 Mockito的不足

  • 不支持局部变量
  • 不支持mock静态方法
  • 不支持mock final修饰的类或方法
  • 不支持mock私有方法

1.2 PowerMock局部变量

 1 package org.example.service;
 2 
 3 import org.example.Domain.User;
 4 import org.example.dao.UserDao;
 5 
 6 public class UserService2 {
 7 
 8     public User findUser(String userName, String password) {
 9         // 需要mock局部变量 userDao
10         UserDao userDao = new UserDao();
11         return userDao.findUser(userName, password);
12     }
13 }
 1 package org.example.powermock;
 2 
 3 import lombok.SneakyThrows;
 4 import org.example.Domain.User;
 5 import org.example.dao.UserDao;
 6 import org.example.service.UserService2;
 7 import org.junit.Test;
 8 import org.junit.runner.RunWith;
 9 import org.powermock.api.mockito.PowerMockito;
10 import org.powermock.core.classloader.annotations.PrepareForTest;
11 import org.powermock.modules.junit4.PowerMockRunner;
12 
13 import static org.junit.Assert.assertEquals;
14 import static org.powermock.api.mockito.PowerMockito.when;
15 import static org.powermock.api.mockito.PowerMockito.whenNew;
16 
17 @RunWith(PowerMockRunner.class)
18 @PrepareForTest({UserService2.class, UserDao.class})
19 public class LocalVariableTest {
20 
21     @Test
22     @SneakyThrows
23     public void findUserTest() {
24         UserService2 userService2 = new UserService2();
25         UserDao userDao = PowerMockito.mock(UserDao.class);
26         whenNew(UserDao.class).withNoArguments().thenReturn(userDao);
27         // 此处用PowerMockito或Mockito的when()都可
28         when(userDao.findUser("zhangsan", "123456")).thenReturn(new User(1L, "zhangsan", "123456"));
29         User user = userService2.findUser("zhangsan", "123456");
30         assertEquals(1, user.getId().longValue());
31     }
32 }

1.3 PowerMock静态方法

package org.example.service;

public class StaticMethod {

    public static String get() {
        return null;
    }
}
package org.example.powermock;

import org.example.service.FinalClass;
import org.example.service.StaticMethod;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.junit.Assert.assertNotNull;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest({StaticMethod.class})
public class StaticMethodTest {

    @Test
    public void getUser() {
        mockStatic(StaticMethod.class);
        when(StaticMethod.get()).thenReturn("");
        String value = StaticMethod.get();
        assertNotNull(value);
    }
}

高版本的Mockito也支持static方法的mock

1.4 PowerMock final类

 1 package org.example.service;
 2 
 3 import org.example.Domain.User;
 4 import org.example.dao.UserDao;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.stereotype.Service;
 7 
 8 @Service
 9 public final class FinalClass {
10 
11     @Autowired
12     private UserDao userDao;
13 
14     public User findUser(String userName, String password) {
15         return userDao.findUser(userName, password);
16     }
18 }

测试中,发现Mockito也支持final类的mock

 1 package org.example.powermock;
 2 
 3 import org.example.Domain.User;
 4 import org.example.dao.UserDao;
 5 import org.example.service.FinalClass;
 6 import org.junit.Test;
 7 import org.junit.runner.RunWith;
 8 import org.mockito.InjectMocks;
 9 import org.mockito.Mock;
10 import org.mockito.junit.MockitoJUnitRunner;
11 
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertNotNull;
14 import static org.powermock.api.mockito.PowerMockito.when;
15 
16 @RunWith(MockitoJUnitRunner.class)
17 public class MockitoTest {
18 
19     @InjectMocks
20     private FinalClass finalClass;
21 
22     @Mock
23     private UserDao userDao;
24 
25     @Test
26     public void findUserTest() {
27         when(userDao.findUser("", "")).thenReturn(new User(1L, "zhangsan1", "123456"));
28         User user = finalClass.findUser("", "");
29         assertNotNull(user);
30         assertEquals("zhangsan1", user.getUserName());
31     }
32 }

PowerMock mock filanl类:

 1 package org.example.powermock;
 2 
 3 import org.example.Domain.User;
 4 import org.example.dao.UserDao;
 5 import org.example.service.FinalClass;
 6 import org.example.service.UserService2;
 7 import org.junit.Test;
 8 import org.junit.runner.RunWith;
 9 import org.mockito.InjectMocks;
10 import org.mockito.Mock;
11 import org.powermock.core.classloader.annotations.PrepareForTest;
12 import org.powermock.modules.junit4.PowerMockRunner;
13 
14 import static org.junit.Assert.assertNotNull;
15 import static org.powermock.api.mockito.PowerMockito.when;
16 
17 @RunWith(PowerMockRunner.class)
18 @PrepareForTest({FinalClass.class})
19 public class FinalClassTest {
20 
21     @InjectMocks
22     private FinalClass finalClass;
23 
24     @Mock
25     private UserDao userDao;
26 
27     @Test
28     public void findUserTest() {
29         when(userDao.findUser("", "")).thenReturn(new User(1L, "zhangsan", "123456"));
30         User user = finalClass.findUser("", "");
31         assertNotNull(user);
32     }
33 }

1.5 PowerMock私有方法

package org.example.service;

import org.example.Domain.User;

public class PrivateMethod {

    public User findUser(String userName) {
        // do something
        return getUser(userName);
    }

    private User getUser(String userName) {
        return null;
    }

}
package org.example.powermock;

import lombok.SneakyThrows;
import org.example.Domain.User;
import org.example.service.PrivateMethod;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.junit.Assert.assertNotNull;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.when;

@RunWith(PowerMockRunner.class)
@PrepareForTest({PrivateMethod.class})
public class PrivateMethodTest {

    @SneakyThrows
    @Test
    public void findUserTest() {
        PrivateMethod privateMethod = spy(new PrivateMethod());
        when(privateMethod, "getUser", "").thenReturn(new User(1L, "zhangsan", "123456"));
        User user = privateMethod.findUser("");
        assertNotNull(user);
    }
}

1.6 说明

虽然PowerMock功能强大,但不推荐使用, 因为其一些功能可能打破了java的设计理念,编写单元测试时,尽量编写可测试的代码,如果代码不可测,很可能是其结构设计有问题

2 Spring-test

2.1 多层依赖嵌套

package org.example.controller;

import org.example.Domain.User;
import org.example.dao.UserDao;
import org.example.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

/**
 * @RunWith(SpringJUnit4ClassRunner.class) 启动spring单元测试运行器
 * @Import({UserController.class}) 使@Autowired UserController生效
 */
@RunWith(SpringJUnit4ClassRunner.class)
@Import({UserController.class})
public class UserControllerTest1 {

    @Autowired
    private UserController userController;

    /**
     * spy对象并注入spring容器
     */
    @SpyBean
    private UserService userService;

    /**
     * mock对象并注入spring容器
     */
    @MockBean
    private UserDao userDao;

    @Test
    public void findUserTest() {
        when(userDao.findUser("zhangsan", "123456")).thenReturn(new User(100L, "zhangsan", "123456"));
        User user = userController.findUser("zhangsan", "123456");
        assertEquals(100L, user.getId().longValue());
    }
}

3 Mybatis + H2

init.sql:

1 create table if not exists user_info (
2 `id` int(11) not null,
3 `user_name` varchar(256) not null,
4 `password` varchar(256) not null
5 );

dataSource.xml:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xmlns:p="http://www.springframework.org/schema/p"
 4        xmlns="http://www.springframework.org/schema/beans"
 5        xmlns:jdbc="http://www.springframework.org/schema/jdbc"
 6        xmlns:context="http://www.springframework.org/schema/context"
 7        xsi:schemaLocation="http://www.springframework.org/schema/beans
 8        http://www.springframework.org/schema/beans/spring-beans.xsd
 9        http://www.springframework.org/schema/tx
10        http://www.springframework.org/schema/tx/spring-tx.xsd
11        http://www.springframework.org/schema/jdbc
12        http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
13        http://www.springframework.org/schema/context
14        http://www.springframework.org/schema/context/spring-context.xsd">
15 
16     <jdbc:embedded-database id="h2TestDataSource" type="H2" database-name="testDataSource;DATABASE_TO_UPPER=false;MODE=MYSQL;">
17         <!-- 这里init.sql是需要初始化的文件 -->
18         <jdbc:script location="classpath:init.sql"/>
19     </jdbc:embedded-database>
20 
21     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
22         <property name="dataSource" ref="h2TestDataSource"/>
23         <!--<property name="mapperLocations">
24             <list>
25                 &lt;!&ndash; 这里的value换成真实的mybatis的mapper文件地址 &ndash;&gt;
26                 <value>classpath:mybatis/*Mapper.xml</value>
27             </list>
28         </property>-->
29     </bean>
30 
31     <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
32         <constructor-arg ref="sqlSessionFactory"/>
33     </bean>
34 
35     <!-- 配置扫描Mapper接口的包路径 -->
36     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
37         <!-- xxxMapper.java对应的包名 -->
38         <property name="basePackage" value="org.example.mapper"/>
39         <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
40     </bean>
41 
42     <!-- 数据库事务管理配置 -->
43     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
44         <property name="dataSource" ref="h2TestDataSource"/>
45     </bean>
46 
47     <!-- spring扫描路径 -->
48     <context:component-scan base-package="org.example"/>
49 </beans>

UserMapper:

 1 package org.example.mapper;
 2 
 3 import org.apache.ibatis.annotations.Select;
 4 import org.example.Domain.User;
 5 import org.springframework.stereotype.Repository;
 6 
 7 @Repository
 8 public interface UserMapper {
 9 
10     @Select("select * from user_info where id = #{id}")
11     User findUserById(Long id);
12 }

Test:

 1 package org.example;
 2 
 3 import org.example.Domain.User;
 4 import org.example.mapper.UserMapper;
 5 import org.junit.Test;
 6 import org.junit.runner.RunWith;
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.test.context.ContextConfiguration;
 9 import org.springframework.test.context.jdbc.Sql;
10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11 
12 import static org.junit.jupiter.api.Assertions.assertEquals;
13 import static org.junit.jupiter.api.Assertions.assertNotNull;
14 
15 @RunWith(SpringJUnit4ClassRunner.class)
16 @ContextConfiguration(locations = "classpath:dataSource.xml")
17 public class UserServiceTest {
18 
19     @Autowired
20     private UserMapper userMapper;
21 
22     @Test
23     // 使用该语句先插入一条数据
24     @Sql(statements = {
25             "insert into user_info (id, user_name, password) values(1,'zs','123456');"
26     })
27     public void findUserById() {
28         User user = userMapper.findUserById(1L);
29         assertNotNull(user);
30         assertEquals("zs", user.getUserName());
31     }
32 }

 

标签:单元测试,junit,example,User,import,org,class
From: https://www.cnblogs.com/javaXRG/p/17539204.html

相关文章

  • 单元测试(二)
    本节主要介绍Mockito,接上篇:https://www.cnblogs.com/javaXRG/p/17537364.html1、基础用法1.1工程代码1packageorg.example.Domain;23importlombok.AllArgsConstructor;4importlombok.Data;56@Data7@AllArgsConstructor8publicclassUser{91......
  • 单元测试 - Moq
    测试方法//准备MockIFoo接口varmock=newMock<IFoo>();//配置准备模拟的方法,当调用接口中的DoSomething方法,并传递参数"bing"的时候,返回truemock.Setup(foo=>foo.DoSomething("ping")).Returns(true);//方法的参数中使用了out参数//outargumentsvarou......
  • 软件测试常用工具总结(测试管理、单元测试、接口测试、自动化测试、性能测试、负载测试
    在软件测试的过程中,多多少少都是会接触到一些测试工具,作为辅助测试用的,以提高测试工作的效率,使用好了测试工具,能对测试起到一个很好的作用,同时,有些公司,也会要求掌握一些测试工具,或者,是在面试时,也会被问到测试工具的,比如,在面试时,最常见的问题便是,你在测试时,用的是什么测试工具?或者......
  • 单元测试-异常测试
    前面的文章(Java中的单元测试)已经说过单元测试中的mock测试,大都是正常分支下的测试,异常测试用于测试某些场景下是否会触发指定的异常,用来验证代码逻辑的正确性。目前根据Junit的版本有三种不同的方式,如下:1、@Test注解中的expected属性此方式比较简单,但是存在局限性,就是只能判断异......
  • C#中各单元测试框架比对
    下面是关于NUnit、xUnit.net、MSTest、SpecFlow和FluentAssertions等单元测试框架的优势和适用场景的简要比较:NUnit框架:优势:NUnit是一个历史悠久且成熟的框架,提供了广泛的功能和灵活性。它具有强大的断言库、丰富的扩展插件和广泛的社区支持。劣势:对初学者来说,可能存在一些学习曲线......
  • mybatis单元测试(无需启动容器)
    一、浅析相关类参考文档:https://blog.csdn.net/weixin_44778952/article/details/1096611251ConfigurationMyBatis在启动时会取读取所有配置文件,然后加载到内存中,Configuration类就是承载整个配置的类。SqlSessionFactoryBuilder调用build方法创建SqlSessionFactory,而SqlSessio......
  • 三. 软件工程 --- 单元测试
    1.单元测试(UnitTesting):是对软件中的最小可测试单元进行检查和验证。单元是构造软件系统的基础,只有使每个单元都得到足够的测试,系统的质量才能有可靠的保证,即单元测试是构筑产品质量的基石。 不能把单元测试任务堆积到系统测试阶段,否则大量故障堆积在项目中后期,项目后10%的......
  • Debug Golang源码中的单元测试
    goland配置如上,既可以debuggolang源码中的单元测试。......
  • 自媒体文章审核单元测试
    packagecom.heima.wemedia.test.service;importcom.heima.wemedia.WemediaApplication;importcom.heima.wemedia.service.WmNewsAutoScanService;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.beans.factory.annotation.Autow......
  • 【转】Java 单元测试
    Java单元测试在测试方法上添加@Test注解:   ......