用Mockito测试SpringMVC+Hibernate

译自:Spring 4 MVC+Hibernate 4+MySQL+Maven integration + Testing example using annotations

2017-01-19

目录:

1 目录结构
2 pom.xml
3 Testing Controller Layer
  3.1 com.websystique.springmvc.controller.AppControllerTest
4 Testing Service Layer
  4.1 com.websystique.springmvc.service.EmployeeServiceImplTest
5 Testing Data Layer
  5.1 com.websystique.springmvc.configuration.HibernateTestConfiguration
  5.2 com.websystique.springmvc.dao.EntityDaoImplTest
  5.3 com.websystique.springmvc.dao.EmployeeDaoImplTest
  5.4 src/test/resources/Employee.xml

源代码 : SpringHibernateExample.zip

1 目录结构


返回

2 pom.xml


返回

与 被测项目 Spring 4 MVC+Hibernate 4+MySQL+Maven使用注解集成实例中pom.xml 一样。

其中,

  • Spring-test : 在测试类中使用 spring-test annotations
  • TestNG : 使用testNG作为测试框架
  • Mockito : 使用mockito模拟外部依赖, 比如当测试service时mock dao,关于mockito,请参考Mockito教程
  • DBUnit : 使用DBUnit管理数据,当测试data/dao层时
  • H2 Database : 对数据库层测试,与其说是单元测试不如说是集成测试,使用H2 Database对数据库层进行测试

3 Testing Controller Layer


返回

3.1 com.websystique.springmvc.controller.AppControllerTest

package com.websystique.springmvc.controller;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List; import org.joda.time.LocalDate;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import static org.mockito.Mockito.atLeastOnce; import org.springframework.context.MessageSource;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import com.websystique.springmvc.model.Employee;
import com.websystique.springmvc.service.EmployeeService; public class AppControllerTest { @Mock
EmployeeService service; @Mock
MessageSource message; @InjectMocks
AppController appController; @Spy
List<Employee> employees = new ArrayList<Employee>(); @Spy
ModelMap model; @Mock
BindingResult result; @BeforeClass
public void setUp(){
MockitoAnnotations.initMocks(this);
employees = getEmployeeList();
} @Test
public void listEmployees(){
when(service.findAllEmployees()).thenReturn(employees);
Assert.assertEquals(appController.listEmployees(model), "allemployees");
Assert.assertEquals(model.get("employees"), employees);
verify(service, atLeastOnce()).findAllEmployees();
} @Test
public void newEmployee(){
Assert.assertEquals(appController.newEmployee(model), "registration");
Assert.assertNotNull(model.get("employee"));
Assert.assertFalse((Boolean)model.get("edit"));
Assert.assertEquals(((Employee)model.get("employee")).getId(), 0);
} @Test
public void saveEmployeeWithValidationError(){
when(result.hasErrors()).thenReturn(true);
doNothing().when(service).saveEmployee(any(Employee.class));
Assert.assertEquals(appController.saveEmployee(employees.get(0), result, model), "registration");
} @Test
public void saveEmployeeWithValidationErrorNonUniqueSSN(){
when(result.hasErrors()).thenReturn(false);
when(service.isEmployeeSsnUnique(anyInt(), anyString())).thenReturn(false);
Assert.assertEquals(appController.saveEmployee(employees.get(0), result, model), "registration");
} @Test
public void saveEmployeeWithSuccess(){
when(result.hasErrors()).thenReturn(false);
when(service.isEmployeeSsnUnique(anyInt(), anyString())).thenReturn(true);
doNothing().when(service).saveEmployee(any(Employee.class));
Assert.assertEquals(appController.saveEmployee(employees.get(0), result, model), "success");
Assert.assertEquals(model.get("success"), "Employee Axel registered successfully");
} @Test
public void editEmployee(){
Employee emp = employees.get(0);
when(service.findEmployeeBySsn(anyString())).thenReturn(emp);
Assert.assertEquals(appController.editEmployee(anyString(), model), "registration");
Assert.assertNotNull(model.get("employee"));
Assert.assertTrue((Boolean)model.get("edit"));
Assert.assertEquals(((Employee)model.get("employee")).getId(), 1);
} @Test
public void updateEmployeeWithValidationError(){
when(result.hasErrors()).thenReturn(true);
doNothing().when(service).updateEmployee(any(Employee.class));
Assert.assertEquals(appController.updateEmployee(employees.get(0), result, model,""), "registration");
} @Test
public void updateEmployeeWithValidationErrorNonUniqueSSN(){
when(result.hasErrors()).thenReturn(false);
when(service.isEmployeeSsnUnique(anyInt(), anyString())).thenReturn(false);
Assert.assertEquals(appController.updateEmployee(employees.get(0), result, model,""), "registration");
} @Test
public void updateEmployeeWithSuccess(){
when(result.hasErrors()).thenReturn(false);
when(service.isEmployeeSsnUnique(anyInt(), anyString())).thenReturn(true);
doNothing().when(service).updateEmployee(any(Employee.class));
Assert.assertEquals(appController.updateEmployee(employees.get(0), result, model, ""), "success");
Assert.assertEquals(model.get("success"), "Employee Axel updated successfully");
} @Test
public void deleteEmployee(){
doNothing().when(service).deleteEmployeeBySsn(anyString());
Assert.assertEquals(appController.deleteEmployee("123"), "redirect:/list");
} public List<Employee> getEmployeeList(){
Employee e1 = new Employee();
e1.setId(1);
e1.setName("Axel");
e1.setJoiningDate(new LocalDate());
e1.setSalary(new BigDecimal(10000));
e1.setSsn("XXX111"); Employee e2 = new Employee();
e2.setId(2);
e2.setName("Jeremy");
e2.setJoiningDate(new LocalDate());
e2.setSalary(new BigDecimal(20000));
e2.setSsn("XXX222"); employees.add(e1);
employees.add(e2);
return employees;
}
}

右击该测试类,得到结果如下:

PASSED: deleteEmployee
PASSED: editEmployee
PASSED: listEmployees
PASSED: newEmployee
PASSED: saveEmployeeWithSuccess
PASSED: saveEmployeeWithValidationError
PASSED: saveEmployeeWithValidationErrorNonUniqueSSN
PASSED: updateEmployeeWithSuccess
PASSED: updateEmployeeWithValidationError
PASSED: updateEmployeeWithValidationErrorNonUniqueSSN ===============================================
Default test
Tests run: 10, Failures: 0, Skips: 0
===============================================

解读:

因为被测类AppController依赖EmployeeService , MessageSource, Employee, ModelMap & BindingResult。因此,为了测试AppController,需要提供这些依赖。

    @Mock  //Mock不是真实的对象,它只是用类型的class创建了一个虚拟对象,并可以设置对象行为
EmployeeService service; @Mock
MessageSource message; @InjectMocks //InjectMocks创建这个类的对象并自动将标记@Mock、@Spy等注解的属性值注入到这个中
AppController appController; @Spy //Spy是一个真实的对象,但它可以设置对象行为
List<Employee> employees = new ArrayList<Employee>(); @Spy
ModelMap model; @Mock
BindingResult result;

其中,when..then 模式用于设置对象行为。

另外,需要加入以下代码:

    MockitoAnnotations.initMocks(this); //初始化被注释的[@Mock, @Spy, @Captor, @InjectMocks] 对象

4 Testing Service Layer


返回

4.1 com.websystique.springmvc.service.EmployeeServiceImplTest

package com.websystique.springmvc.service;

import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List; import static org.mockito.Mockito.when; import org.joda.time.LocalDate;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test; import com.websystique.springmvc.dao.EmployeeDao;
import com.websystique.springmvc.model.Employee; public class EmployeeServiceImplTest { @Mock
EmployeeDao dao; @InjectMocks
EmployeeServiceImpl employeeService; @Spy
List<Employee> employees = new ArrayList<Employee>(); @BeforeClass
public void setUp(){
MockitoAnnotations.initMocks(this);
employees = getEmployeeList();
} @Test
public void findById(){
Employee emp = employees.get(0);
when(dao.findById(anyInt())).thenReturn(emp);
Assert.assertEquals(employeeService.findById(emp.getId()),emp);
} @Test
public void saveEmployee(){
doNothing().when(dao).saveEmployee(any(Employee.class));
employeeService.saveEmployee(any(Employee.class));
verify(dao, atLeastOnce()).saveEmployee(any(Employee.class));
} @Test
public void updateEmployee(){
Employee emp = employees.get(0);
when(dao.findById(anyInt())).thenReturn(emp);
employeeService.updateEmployee(emp);
verify(dao, atLeastOnce()).findById(anyInt());
} @Test
public void deleteEmployeeBySsn(){
doNothing().when(dao).deleteEmployeeBySsn(anyString());
employeeService.deleteEmployeeBySsn(anyString());
verify(dao, atLeastOnce()).deleteEmployeeBySsn(anyString());
} @Test
public void findAllEmployees(){
when(dao.findAllEmployees()).thenReturn(employees);
Assert.assertEquals(employeeService.findAllEmployees(), employees);
} @Test
public void findEmployeeBySsn(){
Employee emp = employees.get(0);
when(dao.findEmployeeBySsn(anyString())).thenReturn(emp);
Assert.assertEquals(employeeService.findEmployeeBySsn(anyString()), emp);
} @Test
public void isEmployeeSsnUnique(){
Employee emp = employees.get(0);
when(dao.findEmployeeBySsn(anyString())).thenReturn(emp);
Assert.assertEquals(employeeService.isEmployeeSsnUnique(emp.getId(), emp.getSsn()), true);
} public List<Employee> getEmployeeList(){
Employee e1 = new Employee();
e1.setId(1);
e1.setName("Axel");
e1.setJoiningDate(new LocalDate());
e1.setSalary(new BigDecimal(10000));
e1.setSsn("XXX111"); Employee e2 = new Employee();
e2.setId(2);
e2.setName("Jeremy");
e2.setJoiningDate(new LocalDate());
e2.setSalary(new BigDecimal(20000));
e2.setSsn("XXX222"); employees.add(e1);
employees.add(e2);
return employees;
}
}

右击该测试类,得到结果如下:

PASSED: deleteEmployeeBySsn
PASSED: findAllEmployees
PASSED: findById
PASSED: findEmployeeBySsn
PASSED: isEmployeeSsnUnique
PASSED: saveEmployee
PASSED: updateEmployee ===============================================
Default test
Tests run: 7, Failures: 0, Skips: 0
===============================================

Test Service Layer和Test Control Layer类似,不再详述

5 Testing Data Layer


返回

DAO 或 data Layer测试一直是有争议的话题。我们到底要如何测试?把它当做单元测试的话,就要测试它的每一行代码,这样的话,要mocking所有的外部依赖。但是,我们没有与数据库本身的交互,就没法测data-layer。那么它就变成了集成测试。

通常,我们对DAO Layer做集成测试。这里,我们用in-memory H2 database做集成测试。

5.1 com.websystique.springmvc.configuration.HibernateTestConfiguration

package com.websystique.springmvc.configuration;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate4.HibernateTransactionManager;
import org.springframework.orm.hibernate4.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement; /*
* This class is same as real HibernateConfiguration class in sources.
* Only difference is that method dataSource & hibernateProperties
* implementations are specific to Hibernate working with H2 database.
*/ @Configuration
@EnableTransactionManagement
@ComponentScan({ "com.websystique.springmvc.dao" })
public class HibernateTestConfiguration { @Autowired
private Environment environment; @Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(new String[] { "com.websystique.springmvc.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
} @Bean(name = "dataSource")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
} private Properties hibernateProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
properties.put("hibernate.hbm2ddl.auto", "create-drop");
return properties;
} @Bean
@Autowired
public HibernateTransactionManager transactionManager(SessionFactory s) {
HibernateTransactionManager txManager = new HibernateTransactionManager();
txManager.setSessionFactory(s);
return txManager;
}
}

解读:

  • 上面的类与HibernateConfiguration类非常相似,区别仅在 dataSource() & hibernateProperties()这两个方法的实现。
  • 在Sources folder中,它做了几乎同样事情:它用dataSource创建了SessionFacoty,其中,dataSource被配置成可与in-memory database H2一起工作。为了使hibernate与H2一起工作,设置hibernate.dialect为H2Dialect。
  • SessionFacoty会被注入到AbstractDao,而后当测试EmployeeDaoImpl类时,EmployeeDaoImpl会使用SessionFacoty。

5.2 com.websystique.springmvc.dao.EntityDaoImplTest

该类是所有测试累的基类

package com.websystique.springmvc.dao;

import javax.sql.DataSource;

import org.dbunit.database.DatabaseDataSourceConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.operation.DatabaseOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests;
import org.testng.annotations.BeforeMethod; import com.websystique.springmvc.configuration.HibernateTestConfiguration; @ContextConfiguration(classes = { HibernateTestConfiguration.class })
public abstract class EntityDaoImplTest extends AbstractTransactionalTestNGSpringContextTests { @Autowired
DataSource dataSource; @BeforeMethod
public void setUp() throws Exception {
IDatabaseConnection dbConn = new DatabaseDataSourceConnection(
dataSource);
DatabaseOperation.CLEAN_INSERT.execute(dbConn, getDataSet());
} protected abstract IDataSet getDataSet() throws Exception; }

解读:

  • AbstractTransactionalTestNGSpringContextTests在某种程度上可以更JUnit的RunWith等价。这个抽象类集成Spring TestContext support到TestNG environment中。
  • 为了在测试中提供数据访问层的支持,它也需要在ApplicationContext中定义datasource和transactionManager。我们已在上面的Configuration类中定义了datasource和transactionManager。
  • 由于事物支持,每次测试前一个事物会被默认启动,在每次测试结束后这个事物会被回滚。你可以override这个回滚行为。
  • BeforeTest在测试用执行前,我们将使用DBUnit去clean-insert测试数据库[h2]中的数据样例。这样避免各个测试方法之间的影响
  • 抽象方法getDataSet会在测试类中实现为了在测试前提供真实的测试数据

5.3 com.websystique.springmvc.dao.EmployeeDaoImplTest

package com.websystique.springmvc.dao;

import java.math.BigDecimal;

import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.Assert;
import org.testng.annotations.Test; import com.websystique.springmvc.model.Employee; public class EmployeeDaoImplTest extends EntityDaoImplTest{ @Autowired
EmployeeDao employeeDao; @Override
protected IDataSet getDataSet() throws Exception{
IDataSet dataSet = new FlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("Employee.xml"));
return dataSet;
} /* In case you need multiple datasets (mapping different tables) and you do prefer to keep them in separate XML's
@Override
protected IDataSet getDataSet() throws Exception {
IDataSet[] datasets = new IDataSet[] {
new FlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("Employee.xml")),
new FlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("Benefits.xml")),
new FlatXmlDataSet(this.getClass().getClassLoader().getResourceAsStream("Departements.xml"))
};
return new CompositeDataSet(datasets);
}
*/ @Test
public void findById(){
Assert.assertNotNull(employeeDao.findById(1));
Assert.assertNull(employeeDao.findById(3));
} @Test
public void saveEmployee(){
employeeDao.saveEmployee(getSampleEmployee());
Assert.assertEquals(employeeDao.findAllEmployees().size(), 3);
} @Test
public void deleteEmployeeBySsn(){
employeeDao.deleteEmployeeBySsn("11111");
Assert.assertEquals(employeeDao.findAllEmployees().size(), 1);
} @Test
public void deleteEmployeeByInvalidSsn(){
employeeDao.deleteEmployeeBySsn("23423");
Assert.assertEquals(employeeDao.findAllEmployees().size(), 2);
} @Test
public void findAllEmployees(){
Assert.assertEquals(employeeDao.findAllEmployees().size(), 2);
} @Test
public void findEmployeeBySsn(){
Assert.assertNotNull(employeeDao.findEmployeeBySsn("11111"));
Assert.assertNull(employeeDao.findEmployeeBySsn("14545"));
} public Employee getSampleEmployee(){
Employee employee = new Employee();
employee.setName("Karen");
employee.setSsn("12345");
employee.setSalary(new BigDecimal(10980));
employee.setJoiningDate(new LocalDate());
return employee;
} }

5.4 src/test/resources/Employee.xml

<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<employee id="1" NAME="SAMY" JOINING_DATE="2014-04-16" SALARY="20000" SSN="11111" />
<employee id="2" NAME="TOMY" JOINING_DATE="2014-05-17" SALARY="23000" SSN="11112" />
</dataset>

右击该测试类,得到结果如下:

PASSED: deleteEmployeeByInvalidSsn
PASSED: deleteEmployeeBySsn
PASSED: findAllEmployees
PASSED: findById
PASSED: findEmployeeBySsn
PASSED: saveEmployee ===============================================
Default test
Tests run: 6, Failures: 0, Skips: 0
===============================================

我们以saveEmployee为例解读下执行过程:

1. 在测试方法运行前,Spring会通过@ContextConfiguration注释的EntityDaoImplTest类加载text context,还会通过AbstractTransactionalTestNGSpringContextTests创建beans实例。这只会发生一次。

2. 在bean实例创建前,Spring会创建SessionFactory Bean,并且SessionFactory Bean会被注入dataSource bean(在HibernateTestConfiguration类中定义),见下面属性设置

properties.put("hibernate.hbm2ddl.auto", "create-drop");  

注意:由于hbm2ddl属性,当SessionFactory被创建,与Model类相关的schema会被验证并导出到数据库。这意味着Employee表会在H2数据库中创建。

3. 在测试前,@BeforeMethod注释的方法会被调用,该方法会通知DBUnit连接数据库执行clean-insert,在Employee表插入两个记录(见Employee.xml内容)

4. 现在测试用例saveEmployee将开始执行,在执行开始前,事物将被启动,saveEmployee方法本身将在事物中运行。一旦saveEmployee方法运行完毕,事物会回滚到默认的setup。

5. 测试用例saveEmployee开始执行。它会调用employeeDao.saveEmployee(getSampleEmployee()),被调用者会通过hibernate插入预先定义的Employee到H2 database中。这是关键的一步。在这一个之后,就会有3条记录在H2 database中。

6. 在下一个用例中,@BeforeMethod又会被调用

7. 当所有用例测试完后,session会被关掉,schema会被去除

用Mockito测试SpringMVC+Hibernate的更多相关文章

  1. Maven搭建SpringMVC+Hibernate项目详解 【转】

    前言 今天复习一下SpringMVC+Hibernate的搭建,本来想着将Spring-Security权限控制框架也映入其中的,但是发现内容太多了,Spring-Security的就留在下一篇吧,这 ...

  2. Maven搭建SpringMVC+Hibernate项目详解

    前言 今天复习一下SpringMVC+Hibernate的搭建,本来想着将Spring-Security权限控制框架也映入其中的,但是发现内容太多了,Spring-Security的就留在下一篇吧,这 ...

  3. Maven搭建SpringMVC+Hibernate项目详解(转)

    前言 今天复习一下SpringMVC+Hibernate的搭建,本来想着将Spring-Security权限控制框架也映入其中的,但是发现内容太多了,Spring-Security的就留在下一篇吧,这 ...

  4. 框架篇:Spring+SpringMVC+hibernate整合开发

    前言: 最近闲的蛋疼,搭个框架写成博客记录下来,拉通一下之前所学知识,顺带装一下逼. 话不多说,我们直接步入正题. 准备工作: 1/ IntelliJIDEA的安装配置:jdk/tomcat等..(本 ...

  5. Spring+SpringMVC+Hibernate小案例(实现Spring对Hibernate的事务管理)

    原文地址:https://blog.csdn.net/jiegegeaa1/article/details/81975286 一.工作环境 编辑器用的是MyEclipse,用Mysql数据库,mave ...

  6. springmvc+hibernate

    <本文摘要他人> 1.设计数据库:设计好表结构,最好符合3NF,采用Hibernate tools将设计好的表自动生成对应的实体entity. 1.创建Maven项目,按需映入Maven包 ...

  7. spring+springmvc+hibernate 整合

    三大框架反反复复搭了很多次,虽然每次都能搭起来,但是效率不高.最近重新搭了一次,理顺了思路,整理了需要注意的地方,分享出来. 工具:Eclipse(jdk 1.7) spring和hibernate版 ...

  8. Spring MVC 学习笔记12 —— SpringMVC+Hibernate开发(1)依赖包搭建

    Spring MVC 学习笔记12 -- SpringMVC+Hibernate开发(1)依赖包搭建 用Hibernate帮助建立SpringMVC与数据库之间的联系,通过配置DAO层,Service ...

  9. spring+springmvc+hibernate 礼品管理系统

    spring+springmvc+hibernate template礼品管理系统 1.简单介绍 如标题所示,这篇文章简单写了一个基于spring+springmvc+hibernate templa ...

随机推荐

  1. PAT 天梯赛 L2-005 集合相似度

    set的应用 题目链接 题解 有点像集合的交并操作,直接利用set进行处理,因为set有去重的功能,而且set是利用红黑树实现的,查找速度快O(logN). 代码如下: #include<cst ...

  2. spring mvc3中JACKSON序列化日期格式的问题 - 墙头草的Java - BlogJava

    body { font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI ...

  3. away3d 汽车路线编辑器

    2012年的时候,跟朋友去到一个公司,打算用away3d做一个赛车模拟养成游戏,后来由于种种原因,立项未成,由于朋友已经转行,自己也想对自己做过的事情有一些交代,所以将我负责的部分,赛道编辑器的源码公 ...

  4. iOS10适配——相机,通讯录,麦克风等权限设置

    崩溃:[access] This app has crashed because it attempted to access privacy-sensitive data without a usa ...

  5. D. PolandBall and Polygon BIT + 欧拉公式

    http://codeforces.com/contest/755/problem/D // 我也觉得非平面图不能用欧拉公式,但是也能过,不知道为什么.求大佬留言. 这题其实就是平面图,因为它有很多个 ...

  6. jquery核心功能分析

    作者:zccst 核心功能包括: jQuery是如何定义的,如何调用的,如何扩展的.掌握核心方法是如何实现的,是理解jQuery源码的关键.这里理解了一切豁然开朗. 1,如何定义,即入口 // Def ...

  7. LPC1788的ADC和DAC使用

    #ifndef __ADC1_H_ #define __ADC1_H_ #include "common.h" #include "delay.h" void ...

  8. iOS开发之指纹解锁

    http://blog.csdn.net/hongfengkt/article/details/49868073 前一阵子一直在赶项目进度,没有太多时间写博客,现在终于空闲了,将以前欠下的博客补上来. ...

  9. Jsp属性范围

    IDE:MyEclipse 2014(自带Tomcat 7) Web项目路径: Web项目配置信息: WebRoot --WEB-INF --web.xml <?xml version=&quo ...

  10. LPC2478的SPI使用

    LPC2478的spi使用 LPC2748具有一个SPI控制器,可以当做SPI主机或者从机使用,有以下特性 其使用起来很方便,并且支持中断,使用的寄存器如下 基本上,使用起来就是设置控制为,CPOL ...