又有一段時間沒有來記錄點滴了,最近忙上了物聯網平臺項目,物聯網平臺何其多,我們定位於一個追趕者,說實在的心裏沒有啥譜。
項目中用到了spring boot,spring data JPA等一些相對部門較新的技術,spring boot真是個好東西,將spring 大部分的組件進行了集成,提供開箱即用的功能,還有約定大於配置的原則,讓小白很輕鬆的去將框架搭建起來,接觸它時感覺喜歡上了它。
接下來講下spring JPA與Junit的集成如何進行單元測試。
參考資料
官方的資料權威,百度出來的要麼質量不高,要麼原來寫的比較老,配置差別比較大了,再或者是本身這個問題太弱,哈哈
官方reference
官方示例
項目結構圖
上在有個紅叉叉就不糾結了,公司網絡環境差,有個maven插件沒弄好。
pom文件
這裏主要列出核心部分
<!--繼承父pom-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
<!--引入jpa starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--引入test starter-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--使用mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
其實在這配置這個文件時踩了一個坑,在JPA中有個entitymanager
的概念去管理原來的數據庫連接session
會話,開始採用瞭如下配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</exclusion>
</exclusions>
</dependency>
後面測試一直報錯找不到entitymanagerFactory
,其實明眼一看exclusion
是排除的意思,導致加載時datasource
沒辦法注入,在這種情況可能通過代碼寫Configuration
類或者配置XML文件。
編寫DAO類
這裏講到的是JPA,講主要的DAO類實現,DAO層的結構一般分爲兩層,一層爲DAO接口,主要與驅動類找交道實現增刪除改查、分頁等功能,另一層是DAO模塊與其它模塊交互的service接口,這部分接口是不會怎麼變化的,這樣可以很好的抵抗數據庫的變化而與外部模塊之間的接口發生變化。
實體類TenantEntity
這裏以一個簡單租戶的實體
@Entity
@Table(name = "tenant")
public class TenantEntity implements Serializable {
private static final long serialVersionUID = -6160322787230271783L;
@Id
@Column(name = "id")
private String id;
@Column(name = "name")
private String name;
@Column(name = "additional_info")
private String additionInfo;
public TenantEntity(){}
// TODO attributes get/set method
}
TenantDao接口
public interface TenantDao extends JpaRepository<TenantEntity, String> {
}
一咋看這就是個純接口,那實現去哪裏了呢,沒錯,後面的JPA幫你做了絕大部分數據庫基本操作的功能,至於稍微詳細原理性的探究看看這位博主寫的spring-data-jpa詳解
TenantService接口
一個簡單的save方法
public interface TenantService {
public TenantEntity save(TenantEntity entity);
}
TenantServiceImpl實現
接口實現也炒雞簡單,日誌木有,參數校驗木有。。。。
@Service
public class TenantServiceImpl implements TenantService {
@Autowired
private TenantDao tenantDao;
public TenantEntity save(TenantEntity entity) {
return tenantDao.save(entity);
}
}
編寫測試類
上面的被測代碼基本寫完了,接下來準備測試代碼
配置加載類
配置加載類其實是個空類,但用到了一個關鍵的註解@SpringBootApplication
,這個老牛了,是三個註解的總和@Configuration,@EnableAutoConfiguration,@ComponentScan,其實這個空類是爲了拉起spring窗口,並且將掃描到的bean進行自動配置,以及數據源參數的配置,想想都方便,不過方便的同時就是隱藏了很多細節,不懂原理的話剛開始會比較痛苦。另外有個疑問掃描的包路徑是什麼呢,就是以這個空類所在的包爲基準,對以後的子包進行搜索。
@SpringBootApplication
public class AppConfiguration
{
}
測試基類
爲什麼要寫測試基類呢,其實是爲了方便代碼的複用與維護,不用每個測試類頭上寫配置的註解,另外也可以將測試用到的較通用的方法放到裏面去。
@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource(locations = {"classpath:application-test.properties"})
@SpringBootTest
public abstract class AbstractServiceTest {
@Autowired
protected TenantService tenantService;
protected TenantEntity generateTenant(){
TenantEntity tenant = new TenantEntity();
tenant.setId("130");
tenant.setName("test");
tenant.setAdditionInfo("comba");
return tenant;
}
}
測試類
直接貼代碼了
public class TenantServiceImplTest extends AbstractServiceTest {
@Test
public void saveTenant(){
TenantEntity tenant = generateTenant();
TenantEntity newTenant = tenantService.save(tenant);
Assert.assertEquals(tenant.getId(), newTenant.getId());
Assert.assertEquals(tenant.getName(), newTenant.getName());
}
}
編寫配置文件
配置文件是指配置一些常用參數,數據庫配置參數等。
spring.datasource.url=jdbc:mysql://172.16.18.101:3306/iot?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# JPA (JpaBaseConfiguration, HibernateJpaAutoConfiguration)
spring.data.jpa.repositories.enabled=true
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=update
spring.jpa.open-in-view=true
spring.jpa.show-sql=true
這樣就可以跑起來了。
後話
這個例子比較簡單,只提供了一種使用方式與基本思路,如有更高明的方法,望交流共勉。