您应该对什么进行单元测试? –测试技术3

昨天我在办公室里,和我的一位同事谈论测试,他对编写单元测试有些不服气。

他使用的原因之一是有些测试似乎毫无意义,这使我想到了什么是单元测试,什么也不需要打扰。

考虑下面一个简单的不可变的Name Bean,其中包含一个构造函数和一堆getter。

在这个示例中,我将让代码说明一切,因为我希望任何测试都是毫无意义的。

public class Name {private final String firstName;private final String middleName;private final String surname;public Name(String christianName, String middleName, String surname) {this.firstName = christianName;this.middleName = middleName;this.surname = surname;}public String getFirstName() {return firstName;}public String getMiddleName() {return middleName;}public String getSurname() {return surname;}
}

……只是为了强调这一点,这是毫无意义的测试代码:

public class NameTest {private Name instance;@Beforepublic void setUp() {instance = new Name("John", "Stephen", "Smith");}@Testpublic void testGetFirstName() {String result = instance.getFirstName();assertEquals("John", result);}@Testpublic void testGetMiddleName() {String result = instance.getMiddleName();assertEquals("Stephen", result);}@Testpublic void testGetSurname() {String result = instance.getSurname();assertEquals("Smith", result);}
}

测试此类毫无意义的原因是该代码不包含任何逻辑。 但是,当您向Name类添加如下内容时:

public String getFullName() {if (isValidString(firstName) && isValidString(middleName) && isValidString(surname)) {return firstName + " " + middleName + " " + surname;} else {throw new RuntimeException("Invalid Name Values");}}private boolean isValidString(String str) {return isNotNull(str) && str.length() > 0;}private boolean isNotNull(Object obj) {return obj != null;}

…然后整个情况发生了变化。 以if语句的形式添加一些逻辑会生成大量测试:

@Testpublic void testGetFullName_with_valid_input() {instance = new Name("John", "Stephen", "Smith");final String expected = "John Stephen Smith";String result = instance.getFullName();assertEquals(expected, result);}@Test(expected = RuntimeException.class)public void testGetFullName_with_null_firstName() {instance = new Name(null, "Stephen", "Smith");instance.getFullName();}@Test(expected = RuntimeException.class)public void testGetFullName_with_null_middleName() {instance = new Name("John", null, "Smith");instance.getFullName();}@Test(expected = RuntimeException.class)public void testGetFullName_with_null_surname() {instance = new Name("John", "Stephen", null);instance.getFullName();}@Test(expected = RuntimeException.class)public void testGetFullName_with_no_firstName() {instance = new Name("", "Stephen", "Smith");instance.getFullName();}@Test(expected = RuntimeException.class)public void testGetFullName_with_no_middleName() {instance = new Name("John", "", "Smith");instance.getFullName();}@Test(expected = RuntimeException.class)public void testGetFullName_with_no_surname() {instance = new Name("John", "Stephen", "");instance.getFullName();}

因此,鉴于我刚刚说过,您不需要测试不包含任何逻辑语句的对象,并且在逻辑 语句列表中,我将包含if并与所有运算符一起切换 (+-*- ),以及可能发生变化和对象状态的一整套事物。

在此前提下,我建议在我前两篇博客中一直在讨论的Address项目中为地址数据访问对象(DAO)编写单元测试毫无意义。 DAO由AddressDao接口定义,并由JdbcAddress类实现:

public class JdbcAddress extends JdbcDaoSupport implements AddressDao {/*** This is an instance of the query object that'll sort out the results of* the SQL and produce whatever values objects are required*/private MyQueryClass query;/** This is the SQL with which to run this DAO */private static final String sql = "select * from addresses where id = ?";/*** A class that does the mapping of row data into a value object.*/class MyQueryClass extends MappingSqlQuery<address> {public MyQueryClass(DataSource dataSource, String sql) {super(dataSource, sql);this.declareParameter(new SqlParameter(Types.INTEGER));}/*** This the implementation of the MappingSqlQuery abstract method. This* method creates and returns a instance of our value object associated* with the table / select statement.* * @param rs*            This is the current ResultSet* @param rowNum*            The rowNum* @throws SQLException*             This is taken care of by the Spring stuff...*/@Overrideprotected Address mapRow(ResultSet rs, int rowNum) throws SQLException {return new Address(rs.getInt("id"), rs.getString("street"),rs.getString("town"), rs.getString("post_code"),rs.getString("country"));}}/*** Override the JdbcDaoSupport method of this name, calling the super class* so that things get set-up correctly and then create the inner query* class.*/@Overrideprotected void initDao() throws Exception {super.initDao();query = new MyQueryClass(getDataSource(), sql);}/*** Return an address object based upon it's id*/@Overridepublic Address findAddress(int id) {return query.findObject(id);}}

在上面的代码中,接口中的唯一方法是:

@Overridepublic Address findAddress(int id) {return query.findObject(id);}

……这实际上是一种简单的吸气方法。 在我看来,这是可以的,因为DAO中确实不应包含属于AddressService的任何业务逻辑,该业务逻辑应具有大量的单元测试。

您可能要决定是否要为MyQueryClass编写单元测试。 对我来说这是一个临界情况,所以我期待任何评论……

我猜想有人会不同意这种方法,说您应该测试JdbcAddress对象,这是真的,我亲自为其编写了一个集成测试,以确保我使用的数据库可以正常运行,并且可以理解我的数据库SQL,并且两个实体(DAO和数据库)可以互相通信,但是我不会打扰对其进行单元测试。

总而言之,单元测试必须是有意义的,并且对“有意义”的良好定义是被测对象必须包含一些独立的逻辑。

参考: 您应该对什么进行单元测试? – Captain Debug博客上的 JCG合作伙伴 测试技术3

相关文章 :

  • 测试技巧–不编写测试
  • 端到端测试的滥用–测试技术2
  • 常规单元测试和存根–测​​试技术4
  • 使用模拟的单元测试–测试技术5
  • 为旧版代码创建存根–测试技术6
  • 有关为旧版代码创建存根的更多信息–测试技术7
  • 为什么要编写单元测试–测试技巧8
  • 一些定义–测试技术9
  • 使用FindBugs产生更少的错误代码
  • 在云中开发和测试

翻译自: https://www.javacodegeeks.com/2011/11/what-should-you-unit-test-testing.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/374067.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java基础知识系列---垃圾收集

1 为什么要使用垃圾回收机制&#xff1f; “垃圾收集”暗示程序不再需要的对象就是垃圾&#xff0c;可以被丢弃。更精确&#xff0c;更新的说法是“内存回收”。 1.1 新对象的使用 当一个对象不再被程序所引用时&#xff0c;他所使用的堆空间可以被回收&#xff0c;以便于被后续…

经济

联合国&#xff0c;美苏英法中 国家要外汇储备干什么&#xff1f; 01年加入WTO &#xff0c;美国躲开 WTO 另起炉灶 TPP 诺贝尔经济学奖得主 克鲁格蛮 触动利益比触动灵魂还困难 SDR IMF 转载于:https://www.cnblogs.com/zrui513/p/5014593.html

wxpython的sizer_wxPython BoxSizer布局

Box wx.BoxSizer(wxHORIZONTAL) Box wx.BoxSizer(wxVERTICAL)Add() 方法(从wxSizer继承)它附加到sizer的下一行/列。Box.Add(control, proportion, flag, border)proportion 参数控制的控件响应于所述容器的尺寸改变其大小。各种flag 参数的组合决定控件在sizer的外观。下面是…

NYOJ 6 喷水装置(一)

喷水装置&#xff08;一&#xff09; 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB 难度&#xff1a;3描述 现有一块草坪&#xff0c;长为20米&#xff0c;宽为2米&#xff0c;要在横中心线上放置半径为Ri的喷水装置&#xff0c;每个喷水装置的效果都会让以它为…

如何部署Zabbix服务端

部署环境 RHEL 6.7 Zabbix-server 2.2.14 安装zabbix官方源 # wget http://repo.zabbix.com/zabbix/2.2/rhel/6/x86_64/zabbix-release-2.2-1.el6.noarch.rpm # rpm -ivh zabbix-release-2.2-1.el6.noarch.rpm 安装zabbix-server # yum install zabbix zabbix-server-mysql zab…

Google App Engine上的Spring MVC和REST

前段时间&#xff0c;我写了一篇关于如何使用Spring MVC实现Restful Web API的文章 。 阅读我以前的文章以了解它。 在那篇文章中&#xff0c;开发了一个简单的Rest示例。 为了测试该应用程序&#xff0c;将文件复制到Web服务器&#xff08;例如Tomcat &#xff09;中&#xff…

SALT+HASH撒盐加密

#region 撒盐加密string salt Guid.NewGuid().ToString();byte[] passwordAndSaltBytes System.Text.Encoding.UTF8.GetBytes(model.Password salt);byte[] hashBytes new System.Security.Cryptography.SHA256Managed().ComputeHash(passwordAndSaltBytes);string hashStr…

python 子串是否在字符串中_python七种方法判断字符串是否包含子串

1. 使用 in 和 not inin 和 not in 在 Python 中是很常用的关键字&#xff0c;我们将它们归类为 成员运算符。使用这两个成员运算符&#xff0c;可以很让我们很直观清晰的判断一个对象是否在另一个对象中&#xff0c;示例如下&#xff1a;>>> "llo" in &quo…

NYOJ 8 一种排序

一种排序 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;3描述现在有很多长方形&#xff0c;每一个长方形都有一个编号&#xff0c;这个编号可以重复&#xff1b;还知道这个长方形的宽和长&#xff0c;编号、长、宽都是整数&#xff1b;现在要…

css3中的background

对background的两种运用&#xff1a;一是background中的线性渐变&#xff0c;background: linear-gradient(to bottom,#0e7bef,#0d73da);这个是对背景颜色从上到下的一种线性渐变&#xff08;linear-gradient&#xff09;&#xff0c;两个颜色参数是从第一个颜色参数渐变到第二…

Oracle JRockit Mission Control 4.1发布

Oracle发布了以前的仅JRockit专用工具Mission Control Suite&#xff08;JRMC&#xff09;的新版本。 4.1版本是次要版本升级&#xff0c;直接遵循4.0.1&#xff08;该版本发布于2010年中期&#xff09;。 但是&#xff0c;即使版本号表明是次要的升级&#xff0c;您仍然可以在…

pe安装usb3.0驱动_电脑店U盘启动盘制作工具下载安装须知

电脑店U盘启动盘制作工具集成最全面的硬件驱动&#xff0c;精心挑选的系统维护工具&#xff0c;加上独有人性化的设计&#xff0c;具备较强的兼容性、稳定性和安全性。能够完美兼容台式机、品牌机及笔记本等新老机型&#xff0c;且安全无毒&#xff0c;电脑店一键U盘启动盘制作…

Webwork【02】前端OGNL试练

1.OGNL 出现的意义 在mvc中&#xff0c;数据是在各个层次之间进行流转是一个不争的事实。而这种流转&#xff0c;也就会面临一些困境&#xff0c;这些困境&#xff0c;是由于数据在不同世界中的表现形式不同而造成的&#xff1a; a. 数据在页面上是一个扁平的&#xff0c;不带数…

python ATM购物程序

需求&#xff1a; 模拟实现一个ATM 购物商城程序 额度 15000或自定义实现购物商城&#xff0c;买东西加入 购物车&#xff0c;调用信用卡接口结账可以提现&#xff0c;手续费5%每月22号出账单&#xff0c;每月10号为还款日&#xff0c;过期未还&#xff0c;按欠款总额 万分之5…

NYOJ 10 skiing

skiing 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;5描述Michael喜欢滑雪百这并不奇怪&#xff0c; 因为滑雪的确很刺激。可是为了获得速度&#xff0c;滑的区域必须向下倾斜&#xff0c;而且当你滑到坡底&#xff0c;你不得不再次走上坡或…

Spring的REST服务发现性,第5部分

这是有关使用Spring 3.1和Spring Security 3.1和基于Java的配置来建立安全的RESTful Web Service的系列文章的第五篇。 上一篇文章介绍了RESTful服务HATEOAS的可发现性的概念&#xff0c;然后介绍了一些由测试驱动的实际方案。 本文将重点介绍可发现性的实际实现以及使用Spring…

postman使用_postman如何使用集合断言?

在postman中&#xff0c;大家都使用过断言&#xff0c;但是我们使用的断言都是针对每一个接口或者是每一个用例添加的&#xff0c;那么是否有可以同时对多个用例或接口添加断言呢 &#xff1f; 答案是肯定有的。那么接下来我就带领大家认识下Postman中的批量断言&#xff0c;也…

纪念我的leetcode开门之旅

15.12.3在朋友的建议下开始了leetcode之旅&#xff0c;上面的题目先捡简单的刷吧。。。转载于:https://www.cnblogs.com/thewaytomakemiracle/p/5016825.html

NYOJ 16 矩形嵌套

矩形嵌套 时间限制&#xff1a;3000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;4描述有n个矩形&#xff0c;每个矩形可以用a,b来描述&#xff0c;表示长和宽。矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d&#xff08;相当于旋转X90度&…

沉思滥用:“强力使用,破坏滥用”

英国前首相本杰明迪斯雷利&#xff08;Benjamin Disraeli&#xff09;曾有一个古老的说法&#xff0c;说谎言分为三种&#xff1a;“谎言&#xff0c;该死的谎言和统计数据”。 这里的暗示是统计数据很容易弥补它们是不可靠的。 但是&#xff0c;统计学在经验科学中得到了广泛的…