`

spring日记(十二):实战单元测试

阅读更多

>> 模拟利器Mockito:

Mockito使用起来非常简单,学习成本低,而且有非常简单的API,测试代码可读性很高。官网地址:http://www.mockito.org/

使用实例:

public class MockitoSampleTest {
    //模拟接口
    UserService mockUserService = mock(UserService.class);
    //模拟实现类
    UserServiceImpl mockServiceImpl = mock(UserServiceImpl.class);
    //基于注解模拟类
        @Mock User mockUser;
     
    @Before
    public void initMocks() {
        //初始化当前测试类所有@Mock注释模拟对象
        MockitoAnnotations.initMocks(this);
    }
     
    @Test
    //模拟接口UserService测试
    public void testMockInterface() {
        //对方法设定返回值 
        when(mockUserService.findUserByUserName("tom")).thenReturn(
                new User("tom", "1234"));
        doReturn(true).when(mockUserService).hasMatchUser("tom", "1234"); 
        //对void方法进行方法预期设定 
        User u = new User("John", "1234");
        doNothing().when(mockUserService).registerUser(u); 
         
        //执行方法调用 
        User user = mockUserService.findUserByUserName("tom");
        boolean isMatch = mockUserService.hasMatchUser("tom","1234");
        mockUserService.registerUser(u);
         
        assertNotNull(user);
        assertEquals(user.getUserName(), "tom");
        assertEquals(isMatch, true);
         
        //验证交互行为
        verify(mockUserService).findUserByUserName("tom");
        //验证方法只调用一次
        verify(mockUserService, times(1)).findUserByUserName("tom");
        //验证方法至少调用一次
        verify(mockUserService, atLeastOnce()).findUserByUserName("tom");
        verify(mockUserService, atLeast(1)).findUserByUserName("tom");
        //验证方法至多调用一次
        verify(mockUserService, atMost(1)).findUserByUserName("tom");
         
        verify(mockUserService).hasMatchUser("tom", "1234");
        verify(mockUserService).registerUser(u);
 
    }
}

>> 测试整合之王Unitils:

Unitils测试框架目的是让单元测试变的更加容易和可维护。Unitils构建在DbUnit与EasyMock项目之上并与JUnit和TestNG相结合。支持数据库测试,支持利用Mock对象进行测试并提供与spring和Hibernate相集成。Unitils设计成以一种高度可配置和松耦合方式添加这些服务到单元测试中。

* unitils-core:核心内核包

* unitils-database:维护测试数据库及连接池

* unitils-DbUnit:使用DbUnit管理测试数据

* unitils-easymock:支持创建Mock和宽松的反射参数匹配

* unitils-inject:支持在一个对象中注入另一个对象

* unitils-mock:整个各种mock,在Mock使用语法上进行简化

* unitils-orm:支持Hibernate、JPA的配置和自动数据库映射检查

* unitils-spring:支持加载spring的上下文配置,并检索和Spring Bean注入

集成spring实例:

public class UserServiceTest extends UnitilsJUnit4 {
    @SpringApplicationContext({"baobaotao-service.xml", "baobaotao-dao.xml"})
    private ApplicationContext applicationContext;
     
    @SpringBean("userService")
    private UserService userService;
     
    @Test
    public void testLoadSpringBean(){
        assertNotNull(applicationContext);
        assertNotNull(userService.findUserByUserName("tom"));
    }
}

集成Dbunit实例:

Dbunit是一个基于JUnit扩展的数据库测试框架,通过使用用户自定义的数据集以及相关操作使得数据库处于一种可知状态,从而使测试自动化、可重复和相对独立。随着Unitils的出现,将spring、hibernate、Dbunit等整合在一起,使得测试DAO层单元测试变得非常简单。

单元测试最重要的特征是独立性和可重复性。对于Service层,可以通过Mockito底层对象和上层对象来获取这种独立性和可重复性。但是DAO层因为是和数据库打交道,其单元测试依赖于数据库中的数据,要实现DAO层单元测试可重复性需要对每次因单元测试引起的数据库中的数据变化进行还原,相当麻烦。

Unitils的出现改变了难测试DAO的局面,它将SpringModule、DatabaseModule、DbUnitModule整合在一起,使得DAO的单元测试变得非常容易。

下面是演示通过excel文件测试DAO层:

Excel数据集工厂

public class MultiSchemaXlsDataSetFactory implements DataSetFactory {
 
    protected String defaultSchemaName;
 
    //初始化
    public void init(Properties configuration, String defaultSchemaName) {
        this.defaultSchemaName = defaultSchemaName;
    }
 
    //创建数据集
    public MultiSchemaDataSet createDataSet(File... dataSetFiles) {
        try {
            MultiSchemaXlsDataSetReader xlsDataSetReader = new MultiSchemaXlsDataSetReader(
                    defaultSchemaName);
            return xlsDataSetReader.readDataSetXls(dataSetFiles);
        } catch (Exception e) {
            throw new UnitilsException("创建数据集失败: "
                    + Arrays.toString(dataSetFiles), e);
        }
    }
 
    // 获取数据集文件的扩展名
    public String getDataSetFileExtension() {
        return "xls";
    }
 
}

Excel数据集读取器:

//EXCEL数据集读取器
public class MultiSchemaXlsDataSetReader {
    private String defaultSchemaName;
 
    public MultiSchemaXlsDataSetReader(String defaultSchemaName) {
        this.defaultSchemaName = defaultSchemaName;
    }
 
    public MultiSchemaDataSet readDataSetXls(File... dataSetFiles) {
        try {
            Map<String, List<ITable>> tableMap = getTables(dataSetFiles);
            MultiSchemaDataSet dataSets = new MultiSchemaDataSet();
            for (Entry<String, List<ITable>> entry : tableMap.entrySet()) {
                List<ITable> tables = entry.getValue();
                try {
                    DefaultDataSet ds = new DefaultDataSet(tables
                            .toArray(new ITable[]{}));
                    dataSets.setDataSetForSchema(entry.getKey(), ds);
                } catch (AmbiguousTableNameException e) {
                    throw new UnitilsException("构造DataSet失败!", e);
                }
            }
            return dataSets;
        } catch (Exception e) {
            throw new UnitilsException("解析EXCEL文件出错:", e);
        }
    }
 
    private Map<String, List<ITable>> getTables(File... dataSetFiles) {
        Pattern pattern = Pattern.compile("\\.");
        Map<String, List<ITable>> tableMap = new HashMap<String, List<ITable>>();
        // 需要根据schema把Table重新组合一下
        try {
            for (File file : dataSetFiles) {
                IDataSet dataSet = new XlsDataSet(new FileInputStream(file));
                String[] tableNames = dataSet.getTableNames();
                for (String each : tableNames) {
                    // 这个实际上不是schema, 是对应的spring的datasouceId
                    String schema = null;
                    String tableName;
                    String[] temp = pattern.split(each);
                    if (temp.length == 2) {
                        schema = temp[0];
                        tableName = temp[1];
                    } else {
                        schema = this.defaultSchemaName;
                        tableName = each;
                    }
                    ITable table = dataSet.getTable(each);
                    if (!tableMap.containsKey(schema)) {
                        tableMap.put(schema, new ArrayList<ITable>());
                    }
                    tableMap.get(schema).add(new XlsTable(tableName, table));
                }
            }
        } catch (Exception e) {
            throw new UnitilsException("创建数据集失败: "
                    + Arrays.toString(dataSetFiles), e);
        }
        return tableMap;
    }
 
    //构造XslTable表
    class XlsTable extends AbstractTable {
        private ITable delegate;
        private String tableName;
 
        public XlsTable(String tableName, ITable table) {
            this.delegate = table;
            this.tableName = tableName;
        }
 
        public int getRowCount() {
            return delegate.getRowCount();
        }
 
        public ITableMetaData getTableMetaData() {
            ITableMetaData meta = delegate.getTableMetaData();
            try {
                return new DefaultTableMetaData(tableName, meta.getColumns(),
                        meta.getPrimaryKeys());
            } catch (DataSetException e) {
                throw new UnitilsException("Don't get the meta info from  "
                        + meta, e);
            }
        }
 
        public Object getValue(int row, String column) throws DataSetException {
            Object delta = delegate.getValue(row, column);
            if (delta instanceof String) {
                if (StringUtils.isEmpty((String) delta)) {
                    return null;
                }
            }
            return delta;
        }
 
    }
}

另外还有一个工具类,用于从excel里面初始化测试数据变成一个pojo类:

/**
 * 从EXCEL数据集文件创建Bean
 */
public class XlsDataSetBeanFactory {
 
    //从DbUnit的EXCEL数据集文件创建多个bean
    public static <T> List<T> createBeans(Class testClass, String file, String tableName,
                                          Class<T> clazz) throws Exception {
        BeanUtilsBean beanUtils = createBeanUtils();
        List<Map<String, Object>> propsList = createProps(testClass, file, tableName);
        List<T> beans = new ArrayList<T>();
        for (Map<String, Object> props : propsList) {
            T bean = clazz.newInstance();
            beanUtils.populate(bean, props);
            beans.add(bean);
        }
        return beans;
    }
 
    //从DbUnit的EXCEL数据集文件创建多个bean
    public static <T> T createBean(Class testClass, String file, String tableName, Class<T> clazz)
            throws Exception {
        BeanUtilsBean beanUtils = createBeanUtils();
        List<Map<String, Object>> propsList = createProps(testClass, file, tableName);
        T bean = clazz.newInstance();
        beanUtils.populate(bean, propsList.get(0));
        return bean;
    }
 
    private static List<Map<String, Object>> createProps(Class testClass, String file,
                                                         String tableName) throws IOException, DataSetException {
        List<Map<String, Object>> propsList = new ArrayList<Map<String, Object>>();
        IDataSet expected = new XlsDataSet(testClass.getResourceAsStream(file));
        ITable table = expected.getTable(tableName);
        Column[] columns = table.getTableMetaData().getColumns();
        for (int i = 0; i < table.getRowCount(); i++) {
            Map<String, Object> props = new HashMap<String, Object>();
            for (Column c : columns) {
                Object value = table.getValue(i, c.getColumnName());
                String propName = underlineToCamel(c.getColumnName());
                props.put(propName, value);
            }
            propsList.add(props);
        }
        return propsList;
    }
 
    private static String underlineToCamel(String str) {
        String pattern[] = str.split("_");
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < pattern.length; i++) {
            if (i == 0) {
                builder.append(pattern[i]);
            } else {
                builder.append(pattern[i].substring(0, 1).toUpperCase());
                builder.append(pattern[i].substring(1));
            }
        }
        return builder.toString();
    }
 
    private static BeanUtilsBean createBeanUtils() {
        ConvertUtilsBean convertUtilsBean = createConverUtils();
        return new BeanUtilsBean(convertUtilsBean);
    }
 
    private static ConvertUtilsBean createConverUtils() {
        DateConverter dateConverter = new DateConverter();
        dateConverter.setPattern("yyyy-MM-dd");
        ConvertUtilsBean convertUtilsBean = new ConvertUtilsBean();
        convertUtilsBean.register(dateConverter, java.util.Date.class);
        convertUtilsBean.register(dateConverter, Timestamp.class);
        convertUtilsBean.register(dateConverter, java.sql.Date.class);
        return convertUtilsBean;
    }
}

接下来配置下unitils,使用我们自定义的数据集工厂类:

DbUnitModule.DataSet.factory.default=sample.unitils.dataset.excel.MultiSchemaXlsDataSetFactory
DbUnitModule.ExpectedDataSet.factory.default=sample.unitils.dataset.excel.MultiSchemaXlsDataSetFactory

DbUnitModule.DataSet.factory.default指的是配置数据集工厂类,可使用@DataSet注解标注数据集,而DbUnitModule.ExpectedDataSet.factory.default指的是验证数据集工厂类,可使用@ExpectedDataSet注解标注验证数据。

用户测试DAO:

@SpringApplicationContext( {"baobaotao-dao.xml" })
public class UserDaoTest extends UnitilsJUnit4 {
 
    @SpringBean("jdbcUserDao")
    private UserDao userDao;
 
 
    @Test
    @DataSet("BaobaoTao.Users.xls")//准备数据 
    public void findUserByUserName() {
        User user = userDao.findUserByUserName("tony");
        assertNull("不存在用户名为tony的用户!", user);
        user = userDao.findUserByUserName("jan");
        assertNotNull("Jan用户存在!", user);
        assertEquals("jan", user.getUserName());
        assertEquals("123456",user.getPassword());
        assertEquals(10,user.getCredits());
    }
 
    // 验证数据库保存的正确性
    @Test
    @ExpectedDataSet("BaobaoTao.ExpectedSaveUser.xls")// 准备验证数据
    public void saveUser()throws Exception  {
        /**
        硬编码创建测试实体
        User u = new User();
        u.setUserId(1);
        u.setUserName("tom");
        u.setPassword("123456");
        u.setLastVisit(getDate("2011-06-06 08:00:00","yyyy-MM-dd HH:mm:ss"));
        u.setCredits(30);
        u.setLastIp("127.0.0.1");
        **/
        //通过XlsDataSetBeanFactory数据集绑定工厂创建测试实体
        User u  = XlsDataSetBeanFactory.createBean("BaobaoTao.SaveUser.xls", "t_user", User.class);
        userDao.save(u);  //执行用户信息更新操作
    }
     
    //验证数据库保存的正确性
    @Test
    @ExpectedDataSet("BaobaoTao.ExpectedSaveUsers.xls")// 准备验证数据
    public void saveUsers()throws Exception  {
        List<User> users  = XlsDataSetBeanFactory.createBeans("BaobaoTao.SaveUsers.xls", "t_user", User.class);
        for(User u:users){
             userDao.save(u);
        }
    }
 
}

>> unitils配置文件unitils.properties说明:

# 这个是整个项目级别的公共配置,如果每个用户也就是开发者去测试的时候可以自己定义unitils-local.properties文件
 
# 启用unitils所需模块
unitils.modules=database,dbunit,hibernate,spring,
# 自定义扩展模块
#unitils.module.dbunit.className=sample.unitils.module.CustomExtModule
 
# 配置数据库连接
database.driverClassName=com.mysql.jdbc.Driver
database.url=jdbc:mysql://localhost:3306/junit?useUnicode=true&characterEncoding=UTF-8
database.dialect=mysql
database.username=root
database.password=123456
 
# 配置数据库维护策略
updateDataBaseSchema.enabled=true
# 配置数据库表创建策略
dbMaintainer.autoCreateExecutedScriptsTable=true
dbMaintainer.script.locations=D:/workspace/spring3/spring3-core/ch16_uint_test/src/main/resources/dbscripts
 
# 配置数据集加载策略
DbUnitModule.DataSet.loadStrategy.default=org.unitils.dbunit.datasetloadstrategy.impl.CleanInsertLoadStrategy
 
# 配置数据集加载工厂
DbUnitModule.DataSet.factory.default=sample.unitils.dataset.excel.MultiSchemaXlsDataSetFactory
DbUnitModule.ExpectedDataSet.factory.default=sample.unitils.dataset.excel.MultiSchemaXlsDataSetFactory
 
# 配置事务策略
DatabaseModule.Transactional.value.default=commit
 
# 配置数据集结构模式XSD生成路径
dataSetStructureGenerator.xsd.dirName=resources/xsd

* 配置数据集加载策略:

默认的数据集加载机制采用先清理后插入的策略,也就是数据在被写入数据库的时候先删除数据集中有对应表的数据,然后将数据集中的数据写入数据库。这个加载策略是可以配置的:

CleanInsertLoadStrategy:先删除dataSet中有关的数据,然后再插入数据

InsertLoadStrategy:只插入数据

RefreshLoadStrategy:有同样key的数据更新,没有的插入

UpdateLoadStrategy:有同样key的数据更新,没有的吧不做任何操作

* 配置事务策略:

默认事务管理是disabled掉的,可以设置DatabaseModule.Transactional.value.default,有几个值:commit、rollback、disabled

>> 测试service层:

@SpringApplicationContext( {"baobaotao-service.xml", "baobaotao-dao.xml" })
public class UserServiceTest extends UnitilsJUnit4 {
    @SpringBean("userService")
    private UserService userService;
     
    private UserDao userDao;
     
    private LoginLogDao loginLogDao;
     
    @Before
    public void init(){
        userDao = mock(UserDao.class);
        loginLogDao = mock(LoginLogDao.class);
 
    }
     
    @Test
    public void hasMatchUser() {
         User user = new User();
         user.setUserName("tom");
         user.setPassword("1234");
         user.setCredits(100);
         doReturn(1).when(userDao).getMatchCount("tom", "1234"); 
         UserServiceImpl userService = new UserServiceImpl();
         ReflectionTestUtils.setField(userService, "userDao", userDao);
         
         boolean isMatch = userService.hasMatchUser("tom", "1234"); 
         assertThat(isMatch,is(true));
         verify(userDao,times(1)).getMatchCount("tom", "1234");
    }
     
    //@Test
    public void findUserByUserName() {
         User user = new User();
         user.setUserName("tom");
         user.setPassword("1234");
         user.setCredits(100);
         doReturn(user).when(userDao).findUserByUserName("tom"); 
         UserServiceImpl userService = new UserServiceImpl();
         ReflectionTestUtils.setField(userService, "userDao", userDao);   
 
         
         User u = userService.findUserByUserName("tom");
         assertNotNull(u);
         assertThat(u.getUserName(),equalTo(user.getUserName()));
         verify(userDao,times(1)).findUserByUserName("tom");
    }
     
     
    @Test
    @DataSet("BaobaoTao.SaveUsers.xls")// 准备验证数据
    public void loginSuccess() {
        User user = userService.findUserByUserName("tom");
        Date now = new Date();
        user.setLastVisit(now);
        userService.loginSuccess(user);
        User u = userService.findUserByUserName("tom");
        assertThat(u.getCredits(),is(105));
    }   
     
}

从上面为用户服务UserService编写的两个测试方法来看,对service层的测试,我们既可以采用JUnit+Unitils+Mockito组合,运用Mockito强大的模块能力,完成service层独立性的单元测试,也就是findUserByUserName()测试方法;也可以采用JUnit+Unitils+Dbunit组合,运用Dbunit强大的数据库维护能力(比如自动回滚,确保每次测试数据的纯洁性)以及Unitils通过DataSet利用Excel、Xml等数据产生方式,完成service+DAO层的集成测试。

>> 测试web层:

spring在org.springframework.mock包中为一些依赖于容器的接口提供了模拟类,这样用户就可以在不启动容器(这里指的是Java EE容器、Servlet容器、Portlet容器等,也就是tomcat、jboss等)的情况下执行单元测试,提高测试效率

* org.springframework.mock.jndi:为JNDI SPI接口提供模拟类以便脱离java EE容器进行测试

* org.springframework.mock.web:为Servlet API接口如HttpServletRequest提供模拟类,以便脱离Servlet容器测试

* org.springframework.mock.web.portlet:为Portlet API接口如PortletRequest提供模拟类,以便可以脱离Portlet容器测试

@SpringApplicationContext( { "classpath:applicationContext.xml",
        "file:D:/workspace/spring3/spring3-core/ch16_uint_test/src/main/webapp/WEB-INF/baobaotao-servlet.xml" })
public class LoginControllerTest extends UnitilsJUnit4 {
    // ① 从Spring容器中加载AnnotationMethodHandlerAdapter
    @SpringBeanByType
    private AnnotationMethodHandlerAdapter handlerAdapter;
 
    // ② 从Spring容器中加载LoginController
    @SpringBeanByType
    private LoginController controller;
 
    @SpringBeanByType
    private RestTemplate restTemplate;
 
    // ③ 声明Request与Response模拟对象
    private MockHttpServletRequest request;
    private MockHttpServletResponse response;
 
    // ④ 执行测试前先初始模拟对象
    @Before
    public void before() {
        request = new MockHttpServletRequest();
        request.setCharacterEncoding("UTF-8");
        response = new MockHttpServletResponse();
    }
 
    @Test
    public void loginCheck() {
        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
        map.add("userName", "john");
        map.add("password", "1234");
        String result = restTemplate.postForObject(
                "http://localhost:8080/ch16/loginCheck.html", map, String.class);
        assertNotNull(result);
        assertThat(result, containsString("用户名或密码错误"));
 
        map.clear();
        map.add("userName", "tom");
        map.add("password", "1234");
        result = restTemplate.postForObject(
                "http://localhost:8080/ch16/loginCheck.html", map, String.class);
        System.out.println(result);
        assertNotNull(result);
        assertThat(result, containsString("tom,欢迎您进入宝宝淘论坛"));
    }
 
    // ⑤ 测试LoginController#loginCheck()方法
    @Test
    public void loginCheckByMock() throws Exception {
        request.setRequestURI("/loginCheck.html");
        request.addParameter("userName", "tom"); // ⑥ 设置请求URL及参数
        request.addParameter("password", "123456");
 
        // ⑦ 向控制发起请求 ” /loginCheck.html”
        ModelAndView mav = handlerAdapter.handle(request, response, controller);
        User user = (User) request.getSession().getAttribute("user");
 
     
        assertNotNull(mav);
        assertEquals(mav.getViewName(), "main");
        assertNotNull(user);
        assertThat(user.getUserName(), equalTo("tom"));// ⑧ 验证返回结果
         
 
        assertThat(user.getCredits(), greaterThan(5));
    }
 
}

上面的测试方法中,loginCheck是通过启动web应用服务器后,利用RestTemplate编写访问客户端进行集成测试,而loginCheckByMock是在不启动web服务器的情况下,直接对controller进行的单元测试,因为Controller用到了Service,而service用到dao,dao访问了数据库,其实也可以利用mockito模拟service层调用,仅仅对controller进行纯粹的单元测试。

>> 使用Selenium模拟真实用户的表单提交以及不同浏览器兼容

Selenium是ThoughtWorks公司开发的基于Web应用的测试工具,直接运行在浏览器中,模拟用户操作,包括Selenium-IDE、Selenium-core、Selenium-rc三部分

下面是测试用的代码示例:

登录页面login.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
    <head>
        <title>宝宝淘论坛登录</title>
    </head>
    <body>
        <c:if test="${!empty error}">
            <font color="red"><c:out value="${error}" /></font>
        </c:if>        
        <form action="<c:url value="/loginCheck.html"/>" method= "post">
            用户名:
            <input type="text" name="userName">
            <br>
            密 码:
            <input type="password" name="password">
            <br>
            <input id="loginBtn" type="submit" value="登录" />
            <input type="reset" value="重置" />
        </form>
    </body>
</html>

主页面main.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <title>宝宝淘论坛</title>
  </head>
  <body>
      ${user.userName},欢迎您进入宝宝淘论坛,您当前积分为${user.credits};
  </body>
</html>

然后就是测试LoginController的测试类:

public class LoginControllerTest {
    //声明WebDriver
    WebDriver driver = null;
     
    @Before
    public void init() {
        driver = new HtmlUnitDriver(); //IE
    }
    @Test
    public void loginCheck(){
        //完全装载页面后将控制返回给测试脚本
        //navigate().to()和get()功能完全一样。
        driver.get("http://localhost/chapter16/index.html"); 
 
        //(XPATH返回第一个匹配到的元素,如果没有匹配到,抛出NoSuchElementException)
        //element = driver.findElement(By.xpath( "//input[@id=’xxx’]" ));
        WebElement userName = driver.findElement(By.name("userName"));  
        WebElement password = driver.findElement(By.name("password"));
         
        //任何页面元素都可以调用sendKeys,
        userName.sendKeys("tom");     
        password.sendKeys("1234");  
         
        //提交表单
        driver.findElement(By.id( "loginBtn" )).click();
        //driver.findElement(By.id( "submit" )).submit(); 要求element必须在表单中,否则抛出NoSuchElementException
 
        //验证返回的主页面 main.jsp
        assertThat(driver.getTitle(), equalTo("宝宝淘论坛"));
        assertThat(driver.getPageSource(), containsString("tom"));
        WebElement body  = driver.findElement(By.xpath( "//body" ));
        assertThat(body.getText(), containsString("tom,欢迎您进入宝宝淘论坛"));
    }
     
}

总结web层测试:

从以上对LoginController编写的三个测试方法可以看出,对Web层的测试,

* 我们既可以采用JUnit+Unitils+Spring Mock组合,运用Spring Mock模拟依赖于容器的接口实例,如HttpServletRequest、ServletContext等,完成Web层中Controller独立性测试

* 也可以采用JUnit+Unitils+Spring RestTemplate,完成Web层继承测试

* 还可以采用JUnit+Selenium组合,来模拟真实用户的操作以及跨浏览器兼容测试

 

本人博客已搬家,新地址为:http://yidao620c.github.io/

分享到:
评论

相关推荐

    spring mvc的简单单元测试

    Spring MVC 提供了对单元测试的良好支持,使得我们可以方便地测试控制器、服务层以及数据访问层。 在Spring MVC中进行单元测试,我们通常会用到以下关键技术和工具: 1. **JUnit**:JUnit是Java编程语言中最常用的...

    spring单元测试包

    spring单元测试包spring单元测试包spring单元测试包spring单元测试包spring单元测试包

    spring MVC junit 单元测试(controller)

    在Spring MVC框架中,单元测试是确保代码质量的重要步骤,特别是在控制器层(Controller)。这篇博客主要探讨了如何使用JUnit进行Spring MVC Controller的单元测试。在实际开发中,单元测试可以帮助我们尽早发现潜在...

    Struts2+Spring+hibernate中对action的单元测试环境搭建[总结].pdf

    Struts2+Spring+Hibernate 中的Action单元测试环境搭建 在软件开发中,单元测试是一种非常重要的测试方法,可以帮助我们确保代码的可靠性和稳定性。在 Struts2+Spring+Hibernate 框架中,对 Action 的单元测试环境...

    spring-boot实战PDF 完整版和随书源码.7z

    在《Spring Boot实战》这本书中,作者会详细讲解如何使用Spring Boot创建RESTful服务、数据库访问、集成WebSocket、安全控制、测试策略等内容。随书源码涵盖了所有示例项目,读者可以按照书中步骤逐步实践,通过动手...

    Spring3单元测试和集成测试

    在Spring框架中,单元测试和集成测试是软件开发过程中不可或缺的部分。它们确保代码的质量和功能的正确性。本文将深入探讨Spring3中的单元测试和集成测试,并提供相关的实践指导。 ### 单元测试 单元测试是指针对...

    SpringBoot 多模块 Serivce 层单元测试

    总结来说,Spring Boot多模块项目中Service层的单元测试是一个系统的过程,涉及到测试环境搭建、测试类编写、模拟对象的使用以及断言和覆盖率的检查。通过有效的单元测试,我们可以保证Service层的业务逻辑正确,...

    Struts+Spring框架下的单元测试[总结].pdf

    对于Action的测试,由于Struts的Action通常会依赖于Spring管理的服务接口,因此在编写单元测试时,需要模拟这些服务的调用。JUnit是常用的Java单元测试框架,可以结合Mockito等库来创建mock对象,模拟Service的行为...

    Spring整合Junit框架进行单元测试Demo

    Spring是一个开源的、全面的企业级应用框架,它简化了开发复杂应用的过程,而JUnit则是一个流行的单元测试框架,用于确保代码的质量和可靠性。当我们需要对Spring框架中的组件进行单元测试时,通常会将JUnit与Spring...

    spring整合单元测试Junit开发包

    在Spring框架中,单元测试是非常重要的一环,因为它可以帮助开发者确保代码的质量和稳定性。Junit是Java中最常用的单元测试框架,它提供了一套简单易用的API来编写和执行测试用例。 在Spring框架中,`spring-test`...

    (Idea)Spring+MyBatis配置及单元测试

    在本文中,我们将深入探讨如何在IntelliJ IDEA(Idea)中建立一个Maven工程,并集成Spring和MyBatis框架,以及如何进行单元测试。这个过程涉及到Java开发中的核心概念,包括依赖管理、配置文件的设置、数据库交互...

    Spring Boot中的单元测试.pdf

    在Spring Boot中,单元测试是确保代码质量和可维护性的重要组成部分。通过单元测试,开发者能够独立验证代码的各个部分,确保它们按照预期工作,并在修改代码后快速发现潜在问题。Spring Boot为此提供了一系列便利...

    Struts2SpringUnitDemo单元测试

    Struts2SpringUnitDemo是一个示例项目,展示了如何在Java应用程序中将Struts2和Spring框架进行集成,并进行单元测试。这两个框架都是Java Web开发中的关键组件,Struts2负责控制层逻辑,Spring则提供了全面的依赖...

    Spring Boot 单元测试和集成测试实现详解

    Spring Boot 单元测试和集成测试实现详解 Springs Boot 是一个基于 Java 的框架,提供了一个便捷的方式来开发基于 Spring 的应用程序。在开发过程中,测试是一个非常重要的步骤,单元测试和集成测试是其中的两种...

    基于springboot+springcloud实现的电商网站项目源代码+数据库,spring cloud进行微服务框架开发

    Spring cloud 实战电商网站项目( 模块) 目的: 综合应用 spring cloud进行微服务架构开发。 开发环境 操作系统 : windows Java环境 : JDK1.8(不能使用高版本) 开发工具 : Idea 2020 数据库: mysql 5.5以上 ...

    Spring+Boot实战

    此外,书中还会讲解Spring Boot的测试支持,包括单元测试、集成测试和端到端测试,帮助开发者确保代码质量。同时,Spring Boot对Actuator模块的介绍,将让读者了解到如何监控和管理运行中的应用,包括健康检查、指标...

    spring mvc jpa单元测试例子

    在Spring MVC和JPA的开发过程中,单元测试是不可或缺的一部分,它可以帮助我们验证代码的正确性,确保系统各个部分能够按预期工作。本例子聚焦于使用Spring的Test注解进行事务管理的单元测试,这对于数据库操作尤其...

    通过spring管理的web工程的junit单元测试方法四

    在Spring框架中,进行Web工程的JUnit单元测试是软件开发中的关键步骤,它能确保代码的质量和可维护性。本文将深入探讨如何利用Spring管理的Web工程进行单元测试,以及如何借助工具提升测试效率。 首先,理解“通过...

    详解spring cloud如何使用spring-test进行单元测试

    Spring Cloud 中的单元测试 在软件开发中,单元测试是一个非常重要的步骤,它可以帮助开发者确保代码的正确性和稳定性。Spring Cloud 作为一款流行的微服务框架,也提供了对单元测试的支持。本文将介绍如何使用 ...

    最简单的含单元测试的spring boot+activiti集成demo

    【标题】"最简单的含单元测试的spring boot+activiti集成demo" 描述了一种将流行的Spring Boot框架与流程管理工具Activiti结合使用的实践案例。这个集成演示项目旨在帮助开发者快速理解和实现基于Spring Boot的...

Global site tag (gtag.js) - Google Analytics