Spring+SpringMVC+MyBatis+easyUI整合优化篇(四)单元测试实例

<h1>日常啰嗦</h1>

前一篇文章《Spring+SpringMVC+MyBatis+easyUI整合优化篇(三)代码测试》讲了不为和不能两个状态,针对不为,只能自己调整心态了,而对于不能,本文会结合一些实例进行讲解,应该可以使得你掌握单元测试的方法。篇幅所限,所以先写三个类型的测试实例,首先是自己平时写着玩儿的测试类,然后分别是针对数据层和业务层的测试,代码都已经上传到github上了。
我的github地址

<h1>简单的测试</h1>

我们可能常常会碰到这种事情,需要实现一个功能的时候,忽然想不起来该用什么方法了,或者忽然忘记一个方法该怎么用了,这个时候我可能会查一下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
    }

这个只是自己的个人习惯,记忆力有时候真的差。

<h1>数据层单元测试</h1>

针对书籍模块的测试类,讲解在代码中:

@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到本地进行测试,并根据上面几个方法写一下自己的测试用例。

<h1>service的单元测试</h1>

其实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的事务管理事务传播属性,想了解的可以自己去查询一下。

<h1>总结</h1>

本篇主要讲了数据层和业务层的测试,下一篇主要会讲一下controller控制层的测试,睡觉啦...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容