前言
前一篇文章《Spring+SpringMVC+MyBatis+easyUI整合優化篇(三)代碼測試》講了不為和不能兩個狀態,針對不為,只能自己調整心態了,而對於不能,本文會結合一些實例進行講解,應該可以使得你掌握單元測試的方法。篇幅所限,所以先寫三個類型的測試實例,首先是自己平時寫着玩兒的測試類,然后分別是針對數據層和業務層的測試,代碼都已經上傳到github上了。
我的github地址
簡單的測試
我們可能常常會碰到這種事情,需要實現一個功能的時候,忽然想不起來該用什么方法了,或者忽然忘記一個方法該怎么用了,這個時候我可能會查一下API然后寫一個簡單的測試方法,並沒有明確的要去測試什么功能,只是簡單的驗證一個函數的用法,或者自己實在不確定一個方法該怎么用了,用這種方式加深一下印象。
// 得到MD5加密的內容
@Test
public void md5Test() {
System.out.println(MD5Util.MD5Encode("ssm-maven-secret", "UTF-8"));
//83d8d99f45f62461cc7b7ee76b448cb0
}
// 通過substring()獲取文件名
@Test
public void subStringTest() {
//通過substring()獲取文件名
String url = "https://s.doubanio.com/f/shire/5522dd1f5b742d1e1394a17f44d590646b63871d/pics/book-default-medium.gif";
url = url.substring(url.lastIndexOf("/") + 1);
System.out.println(url);
//book-default-medium.gif
}
這個只是自己的個人習慣,記憶力有時候真的差。
數據層單元測試
針對書籍模塊的測試類,講解在代碼中:
@RunWith(SpringJUnit4ClassRunner.class) //指定測試用例的運行器 這里是指定了Junit4
@ContextConfiguration("classpath:applicationContext.xml")//裝配Spring
public class BookDaoTest {
//自動注入,需要將BookDao納入到Spring容器的管理下,不然會報錯
@Autowired
private BookDao bookDao;
@Test
public void getBookByIdTest() {
Book book1 = bookDao.getBookById("1");
Assert.assertEquals(book1, null);//判斷兩個參數是否相同,返回true的話則測試通過,不然控制台會亮紅燈。
Book book2 = bookDao.getBookById("1002");
Assert.assertEquals(book2.getTitle(), "材料成型概論");
// Assert.assertEquals(book2.getTitle(), "我隨便寫一個");
//寫了三個斷言,可以分別進行測試,也可以根據上面三個斷言自己編寫測試。
}
}
針對書籍模塊的測試類,講解也都在代碼中:
@RunWith(SpringJUnit4ClassRunner.class) //指定測試用例的運行器 這里是指定了Junit4
@ContextConfiguration("classpath:applicationContext.xml")
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
//默認回滾,即此類中的方法即使執行成功,數據也並不會真正的修改,方法執行后會回滾。
//因為對數據庫的增刪改都會回滾,因此便於測試用例的循環利用
//前面書籍模塊的測試由於只有查詢方法所以沒有加這個注解。
//如果想看到數據庫中的數據隨着測試而發生變化可以去掉這個注解。
public class UserDaoTest {
@Autowired
//自動注入,需要將BookDao納入到Spring容器的管理下
private UserDao userDao;
@Test
public void loginTest() {
User user = new User();
user.setUserName("admin");
user.setPassword("123456");
//斷言此姓名和密碼的用戶為空
//密碼並沒有加密,所以登錄失敗,返回的用戶對象為空。
Assert.assertEquals(userDao.login(user), null);
User user2 = new User();
user2.setUserName("admin");
user2.setPassword(MD5Util.MD5Encode("123456", "UTF-8"));
//斷言此姓名和密碼的用戶可以登錄成功,且用戶id為2
Assert.assertTrue(userDao.login(user2).getId() == 2);
//執行下面這個斷言則會報錯。
//Assert.assertTrue(userDao.login(user2).getId() == 3);
}
@Test
public void findUsersTest() {
//斷言此時返回的用戶列表數大於0
Assert.assertTrue(userDao.findUsers(null).size() > 0);
//斷言此時返回的用戶列表數等於3,數字你可以隨便寫,用戶數可能是錯的,如果報錯你會看到控制台一片紅色
Assert.assertTrue(userDao.findUsers(null).size() == 3);
}
@Test
public void getTotalUserTest() {
Assert.assertTrue(userDao.getTotalUser(null) > 0);
Assert.assertTrue(userDao.getTotalUser(null) == 3);
}
//使用update、insert、delete方法時,會得到一個返回值,這個返回值說明了執行一條sql語句后,表中有多少條記錄被影響了。
//比如用update修改一條記錄,如果修改成功了,返回值為1,返回0則是修改失敗。
@Test
public void updateUserTest() {
User user = new User();
user.setId(51);
user.setPassword("1221");
//大於0的意思是成功修改了一條記錄,即修改成功,如果updateUser()方法返回值等於0,即修改失敗
Assert.assertTrue(userDao.updateUser(user) > 0);
User user2 = new User();
user2.setId(1000);
user2.setPassword("234y9823y89hhao");
Assert.assertTrue(userDao.updateUser(user2) > 0);
}
@Test
public void addUserTest() {
User user = new User();
user.setUserName("測試用戶");
user.setPassword(MD5Util.MD5Encode("testuser", "UTF-8"));
//大於0的意思是影響了數據庫中的一條記錄,即添加成功
Assert.assertTrue(userDao.addUser(user) > 0);
}
@Test
public void deleteUserTest() {
Assert.assertTrue(userDao.deleteUser(51) > 0);
}
}
大家可以將代碼pull到本地進行測試,並根據上面幾個方法寫一下自己的測試用例。
service的單元測試
其實service層的單元測試和dao層並沒有太多區別,唯一的不同可能就是service層方法中可以執行多條sql語句,而dao層的方法只能執行一條sql語句,因此這個例子更側重於講一下事務問題。
配置文件:
<!-- 配置事務通知屬性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 定義事務傳播屬性 -->
<tx:attributes>
<!--事務切面中insert開頭的方法會被納入事務管理中-->
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="upd*" propagation="REQUIRED"/>
</tx:attributes>
......
</tx:advice>
<!-- 配置事務切面 -->
<aop:config>
<aop:pointcut id="serviceOperation"
expression="(execution(* com.ssm.maven.core.service.*.*(..)))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
</aop:config>
業務方法:
//通過Spring的配置文件,此方法已經納入到其事務管理下
//發生異常時會觸發事務回滾,數據不會被更改
public int insertStore(Store store) {
int level = Integer.valueOf(store.getLevel());
for (int i = 1; i < level; i++) {
store.setLevel(i + "");
storeDao.insertStore(store);
}
store.setLevel(level + "");
int result = storeDao.insertStore(store);
int i = 10 / 0;
//發生異常,操作回滾.
//可以試着將上面一條語句注釋掉再運行測試用例,看看有什么區別。
return result;
}
測試用例:
@RunWith(SpringJUnit4ClassRunner.class) //指定測試用例的運行器 這里是指定了Junit4
@ContextConfiguration("classpath:applicationContext.xml")
//@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
//不添加此設置,測試service層的事務管理
//service層與dao層的測試時相同的,不同之處,在於service層多數都會在配置文件中配置spring的事務管理
public class StoreServiceTest {
@Autowired
private StoreService storeService;
@Test
public void insertStoreTest() {
Store store = new Store();
store.setLevel("5");
store.setNumber("TEST");
storeService.insertStore(store);
int i = 10 / 0;
//這里發生異常是不會回滾的,因為此方法並沒有被納入事務管理中
}
}
這個例子可能有些簡單,一般業務層方法都會較為復雜,如下:
function(){
-A-
SQL1
-B-
SQL2
-C-
SQL3
-D-
}
那么執行此方法時,無論在A處、B處、C處、D處發生異常,都會觸發事務回滾,關於Spring的事務管理及事務傳播屬性,想了解的可以自己去查詢一下。
總結
本篇主要講了數據層和業務層的測試,下一篇主要會講一下controller控制層的測試,睡覺啦...