精华内容
下载资源
问答
  • 译者感到此言虚:作者从数据库的基本概念到数据库建模,从如何运用规范化原则到如何做成实际的数据库表,从如何保护数据库完整性到如何提高数据库的性能,从数据库的安全机制到并发事务控制,从数据库设计开发的...
  • Sam R.Alapati是世界顶尖的Oracle技术专家,一位经验丰富的数据库管理员,有20多年从业经历。他拥有Oracle OCP DBA证书和HP UNIX System Administrator证书,曾经担任Oracle公司的高级顾问,并在AT&T、雷曼兄弟、...
  •  本书由多位工作在数据库维护一线的工程师合著而成,包含了精心挑选的数据库诊断案例与性能优化实践经验,内容涉及oracle典型错误的分析和诊断,各种sql优化方法(包括调整索引,处理表碎片,优化分页查询,改善...
  • 10.3.1 Oracle的数据库级闪回 507 10.3.2 Oracle的flashback drop功能 511 10.3.3 Oracle 10g的Flashback Version Query 517 10.3.4 通过Flashback Transaction Query进行事务撤销 519 10.3.5 闪回表 520 ...
  •  本书是一本关于oracle database 9i、10g 和11g 数据库体系结构权威图书,涵盖了所有重要oracle 体系结构特性,包括文件、内存结构和进程,锁和闩,事务、并发和多版本,表和索引,数据类型,分区和并行,以及...
  • 每个数据库都有一个或多个不同 API 用于创建,访问,管理,搜索和复制所保存数据。在学习MySQL时会有很多问题,接下来我们一来学习下~1.Mysql 的技术特点是什么?Mysql 数据库软件是一个客户端或服务器系统,...

    MySQL是一种开放源代码的关系型数据库管理系统。数据库按照数据结构来组织、存储和管理数据的仓库。每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据。

    在学习MySQL时会有很多问题,接下来我们一来学习下~

    1.Mysql 的技术特点是什么?

    Mysql 数据库软件是一个客户端或服务器系统,其中包括:支持各种客户端程序和库的多线程SQL 服务器、不同的后端、广泛的应用程序编程接口和管理工具。

    2.一张表,里面有 ID 自增主键,当 insert 了 17 条记录之后,删除了第 15,16,17 条记录,再把 Mysql 重启,再 insert 一条记录,这条记录的 ID 是 18 还是 15 ?

    (1)如果表的类型是 MyISAM,那么是 18因为 MyISAM 表会把自增主键的最大 ID 记录到数据文件里,重启 MySQL 自增主键的最大ID 也不会丢失。

    (2)如果表的类型是 InnoDB,那么是 15InnoDB 表只是把自增主键的最大 ID 记录到内存中,所以重启数据库或者是对表进行OPTIMIZE 操作,都会导致最大 ID 丢失。

    3.Heap 表是什么?

    HEAP 表存在于内存中,用于临时高速存储。BLOB 或 TEXT 字段是不允许的,只能使用比较运算符=,,=>,= < 。HEAP 表不支持 AUTO_INCREMENT,索引不可为 NULL 。

    4.Mysql 服务器默认端口是什么?

    Mysql 服务器的默认端口是 3306。

    5.与 Oracle 相比,Mysql 有什么优势?

    Mysql 是开源软件,随时可用,无需付费。Mysql 是便携式的带有命令提示符的 GUI。使用 Mysql 查询浏览器支持管理。

    6.如何区分 FLOAT 和 DOUBLE?

    浮点数以 8 位精度存储在 FLOAT 中,并且有四个字节。浮点数存储在 DOUBLE 中,精度为 18 位,有八个字节。

    7.区分 CHAR_LENGTH 和 LENGTH?

    CHAR_LENGTH 是字符数,而 LENGTH 是字节数。Latin 字符的这两个数据是相同的,但是对于 Unicode 和其他编码,它们是不同的。

    8.请简洁描述 Mysql 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别?

    SQL 标准定义的四个隔离级别为:

    read uncommited :读到未提交数据

    read committed:脏读,不可重复读

    repeatable read:可重读

    serializable :串行事物

    9.在 Mysql 中 ENUM 的用法是什么?

    ENUM 是一个字符串对象,用于指定一组预定义的值,并可在创建表时使用。Create table size(name ENUM('Smail,'Medium','Large');

    10.如何定义 REGEXP?

    REGEXP 是模式匹配,其中匹配模式在搜索值的任何位置。

    11.CHAR 和 VARCHAR 的区别?

    CHAR 和 VARCHAR 类型在存储和检索方面有所不同。CHAR 列长度固定为创建表时声明的长度,长度值范围是 1 到 255 。当 CHAR 值被存储时,它们被用空格填充到特定长度,检索 CHAR 值时需删除尾随空格。

    12.列的字符串类型可以是什么?

    字符串类型是:SET、BLOB、ENUM、CHAR、TEXT、VARCHAR 。

    13.如何获取当前的 Mysql 版本?

    SELECT VERSION();用于获取当前 Mysql 的版本。

    c878130dc76f26fbcafd9f905170dfb9.png

    觉得有用的小伙伴可以分享转发

    给更多需要的人看到哦~

    9c25f77f50150fa3ada7a6f360e1face.png9c25f77f50150fa3ada7a6f360e1face.png9c25f77f50150fa3ada7a6f360e1face.png

    END

    6ea98d637093cc8e07d87d41a4d2be97.png
    展开全文
  • 本书第1章强调不要把数据库当成一个黑盒,讨论了开发人员必须了解的数据库的基本特性和功能。第2章提供了一个创建Oracle数据库的绝好例子,从中你将深入地了解数据库和实例的概念。第3章介绍了各种类型的文件,特别...
  • 数据库访问低效、框架配置错误、内存使用过度、网页臃肿,以及遵循常见Web性能最佳实践都是应用开发中常见的、影响应用性能的主要陷阱 。技术性能公司Computeware从实际案例总结了贯穿应用始终的八大影响应用性能...

    数据库访问低效、框架配置错误、内存使用过度、网页臃肿,以及不遵循常见Web性能最佳实践都是应用开发中常见的、影响应用性能的主要陷阱 。技术性能公司Computeware从实际案例总结了贯穿应用始终的八大影响应用性能的陷阱,这些陷阱不仅仅局限于应用开发中,还涉及到整个应用交付流程,包括从终端用户到后台系统的所有组件、数据库以及第三方服务等等,望运维人员、架构师、测试人员和开发人员引以为戒。CSDN摘译如下:


    一、臃肿的Web前端

    面向群体:运维人员、架构师、测试人员、开发人员

    通常企业在重构代码、优化SQL语句、应用缓存等方面都作了充足的优化,其中大部分对应用的最终用户并不可见。然而直接与用户交互的Web前端却被常常被完全忽视。

    根据我们跟踪的来源,传递给用户的页面在过去的3-4年里,无论是大小还是复杂度都稳步增长,同时增长的还有用户对性能的要求。企业需要意识到,他们认为重要的其实并不是最重要的,他们更需要解决的是迎合用户的需求。但如何判断Web前端是否臃肿?

    通常的做法是和你的主要竞争对手以及行业领导者比较,同对横向对比更容易设定一个合理的目标。另外,理解为什么用户会离开你的网站也能够帮助解决客户体验问题:离开你网站的主要是哪类人群?臃肿、缓慢的页面上是否有应用功能?


    你可以使用缓存、压缩以及CDN来应对这样的问题,同时应该更严格地去审核每一个新添加的功能,必要时做一些精简,这可以提供更好的用户体验。

    推荐阅读:

    二、缓慢的第三方内容和CDN

    面向群体:运维人员、架构师、测试人员

    仅仅关注自己的内容容易导致忽略外部组织对网站性能的影响。随着企业越来越多地使用第三方资源,应用性能管理变得更加复杂,即使这些第三方服务是为提升性能而引入的。

    通过观察过去12个月的性能峰值时期——比如假日购物季和超级碗——的数据,我们发现了两大趋势——第三方服务在用户集中访问的高峰期难以支撑,CDN也在庞大的流量下艰难应付。

    分析、社会媒体、网络字体以及流行的JavaScript库等等项目往往来自于无法直接控制的第三方服务,但是你却依赖它来保证网站有效、可靠。当这些服务出问题时,用户记住的是“你”出问题了,而对这背后的第三方服务一无所知,导致你的企业品牌受损。

    监视、管理第三方意味着需要将它们当作独立应用、独立的基准、独立的SLA(Service Level Agreement,服务品质协议)或者独立的SLO(Service Level Objective,服务水平目标)。因此你需要自问:

    • 系统进行过负载测试了吗?
    • 网站三大用户高峰期同时遇到时第三方服务是否能够抗住压力?
    • 遇到性能问题时是否存在扩展计划?
    • 过去的12个月最繁忙的8个小时中,网站用户体验达到平均性能要求了吗?


    最后,你的团队还需要应对这样的场景:如果相关第三方服务/CDN遇到严重服务故障或者降低你网站的性能指标怎么办?永远要准备好B计划、C计划,以缓解这些意外的问题。具体操作包括在访问高峰期移除第三方标签、图片、内容;将内容移动到备用云服务商;多CDN间负载平衡;在访问高峰期将用户切换至简化版本的网站,直到流量恢复正常。

    想要真正控制第三方服务,你必须了解其对网站性能的影响,甚至控制第三方组件的方方面面。

    推荐阅读:

    三、框架的错误使用

    面向群体:架构师、开发人员

    通常网站或者应用少不了使用到第三方类库,比如Hibernate、Spring、Telerik RadControls、jQuery、ExtJS、GWT等等,因为这些第三方工具能够让你免于重写很多常见功能代码,大大提升了工作效率,因此这种现状可能永远不会改变。根据我们的调查,很多框架都没有被正确地使用,或者没有根据应用做专门的优化。

    趋势表明开发人员习惯于在网络上寻找框架,往往在简单的示例上做过验证后就应用于企业应用,而并没有验证框架是否支持所有用例、是否易于扩展并且符合需求。在很多情况下,这些框架“仅仅”是需要更好的设置,比如为Hibernate做正确的缓存策略,或者换用高级API方法,访问SharePoint中List数据。

    下面这张图片显示Hibernate多次执行了同一条SQL语句,而在优化的模式下,应该使用缓存来避免之后的重复查询。


    最后,框架常常在更新中提升功能、性能、以及稳定性,您应该仔细查看这些更新以从中受益。常见的案例就是从不更新jQuery,以至于在过旧版本的浏览器中体验糟糕,甚至也无法充分发挥最新IE、Firefox、Chrome浏览器的性能。

    推荐阅读:

    四、网络基础设施问题

    面向群体:运维人员、架构师、测试人员

    网络基础设施是企业经营成功的基础,但是出问题时也难以分析原因,同一个问题可能有不同的起因,运维团队需要应用程序性能监控解决方案,以轻松、快速地将故障域隔离。

    性能问题的代价可能非常昂贵。根据Aberdeen Group的报告,甚至可能降低9%的收入以及64%的生产效率。如果采用的是SAP基础设施,每分钟宕机成本甚至可能高达$15000。


    判断究竟网络还是应用问题可以通过检查网络、服务器时间异常值与基准流量的比较而分辨出。但仅仅目测报告是不足以避免问题的,积极的应用性能管理首先需要及时响应关键衡量值在异常时APM工具发出的警报。

    五、云平台的伸缩性

    面向群体:运维人员、架构师

    云计算提供了一个非常宏伟的承诺:只要你需要,可以提供无尽的资源、无尽的扩展性。这避免了硬件的过度闲置,同时可以随时应对超出预期的性能需求。

    但云计算同样存在陷阱:如果你的应用程序并非为可扩展而设计,硬件上再大的可扩展性也没有意义。同时,你还需要明白,云计算——除非是私有云设施——实际上并不为你所有。直接访问底层硬件要更加困难得多,因此监控起起来也更困难。

    云也不仅仅是一个无穷无尽的CPU、内存和磁盘的资源池,它同样提供了很多其他的服务,例如存储、通知,以及其它必须了解和监控的服务,它们都是非常关键的组件。

    推荐阅读:

    六、过多的数据库调用

    面向群体:架构师、测试人员、开发者

    数据库访问也是我们经常遇到的应用问题,当我们在几乎所有共事的应用中都发现了这一问题。我们注意到一点,被问责的通常是应用对数据库的访问模式而非数据库设置。我们经常看到一条Web请求会查询数千条数据库状态,这背后常常有很多原因。

    下面这张图中显示了某企业应用调用大型机的工作流程,该大型机每次事物会执行225条SQL。通过更仔细地观察我们发现,因为上面提到的原因,同一条声明被请求了数百次。


    除了访问模式问题,我们同时发现某些语句的执行时间过长,在这种情况下,不仅需要关注调整索引指数等数据库,分析这些语句是否可以从应用内优化也至关重要。我们经常遇到很多数据从数据库中被检索出来(使用外部存储),然后迅速被释放(GC过于活跃)。常见的陷阱还有连接池配置错误以及应用维持连接过久导致其它线程访问数据库遭阻塞。

    下面的图片显示某数据库查询执行的事务流程,其中多数需要很长时间来执行。解决这个问题需要同时就在应用和数据库端做优化。


    推荐阅读:

    七、大数据未经优化

    面向群体:运维人员、架构师、测试人员、开发者

    应用需要处理的数据正在持续增长,大数据解决方案(NoSQL、MapReduce……)提供了新的数据存储、处理方案,但是每一项新的技术都需要为你特定的应用做相应的优化。但是这常常被误解,甚至有人认为只要增加一个额外的功能/模块(比如MapReduce)就能处理/存储更多的数据。

    实际上,这仅适用于应用可扩展的情况。

    下面这张图中事务处理的大部分时间都花费在MongoDB上,仔细观察你会发现该框架访问MongoDB时会额外执行一次计数方法,而这是完全不必要的。在本例中,通过简单地消除不必要的调用就获得了15倍的事务性能提升。


    推荐阅读:

    八、隐秘的内存泄漏

    面向群体:架构师、测试人员、开发者

    内存和垃圾回收问题在任何企业应用中都非常突出,原因之一就在于GC的本质常常被人误解。除了常见的内存相关问题,比如高内存使用率、错误的缓存策略,同样的问题还存在于类的加载、过大的类以及本地内存。下面这张图中的的问题就在于需要加载一个庞大的类,它占据了过多的内存,这是给非常糟糕的做法。


    内存泄漏通常会导致内存用尽异常,往往进一步导致虚拟机崩溃,甚至会使用户当前会话和活跃事务的丢失,带来的影响非常负面,因此避免内存泄漏非常有必要。

    此外,高的内存占用率也会导致更为频繁的GC,对用户响应时间产生直接影响,会话会因为长期运行的GC进程而停止。这种情况可以通过优化GC设置来调整,同时保证不“浪费”内存。

    即使equal/hashcode实现错误的相关问题也有可能导致内存问题。

    推荐阅读:

    展开全文
  • 它基于我使用一种非常常见的模式从数据库中检索地址的简单方案: …并且我提出了这样的想法:任何包含任何逻辑的类都需要进行单元测试。 在其中,我包括了我的数据访问对象DAO,而不是对此类进行集成测试以...
    我的上一个博客是有关测试代码的方法以及讨论您要做和不需要进行测试的方法的一系列博客中的第三篇。 它基于我使用一种非常常见的模式从数据库中检索地址的简单方案:

    …并且我提出了这样的想法:任何不包含任何逻辑的类都不需要进行单元测试。 在其中,我包括了我的数据访问对象DAO,而不是对此类进行集成测试以确保其与数据库协同工作。

    今天的博客涵盖编写常规或经典的单元测试,该测试使用存根对象强制实现测试主题隔离。 我们将要测试的代码再次是AddressService

    @Component
    public class AddressService {
    
      private static final Logger logger = LoggerFactory.getLogger(AddressService.class);
    
      private AddressDao addressDao;
    
      /**
       * Given an id, retrieve an address. Apply phony business rules.
       * 
       * @param id
       *            The id of the address object.
       */
      public Address findAddress(int id) {
    
        logger.info("In Address Service with id: " + id);
        Address address = addressDao.findAddress(id);
    
        address = businessMethod(address);
    
        logger.info("Leaving Address Service with id: " + id);
        return address;
      }
    
      private Address businessMethod(Address address) {
    
        logger.info("in business method");
    
        // Apply the Special Case Pattern (See MartinFowler.com)
        if (isNull(address)) {
          address = Address.INVALID_ADDRESS;
        }
    
        // Do some jiggery-pokery here....
    
        return address;
      }
    
      private boolean isNull(Object obj) {
        return obj == null;
      }
    
      @Autowired
      @Qualifier("addressDao")
      void setAddressDao(AddressDao addressDao) {
        this.addressDao = addressDao;
      }
    }

    迈克尔·费瑟(Michael Feather)的书《有效使用旧版代码》指出,在以下情况下,测试不是单元测试:

    1. 它与数据库对话。
    2. 它通过网络进行通信。
    3. 它涉及文件系统。
    4. 您必须对环境做一些特殊的事情(例如编辑配置文件)才能运行它。

    为了遵守这些规则,您需要将测试对象与系统的其余部分隔离开来,这就是存根对象的所在。存根对象是注入到您的对象中的对象,用于在测试情况下替换实际对象。 马丁·福勒(Martin Fowler)在他的论文《 莫克斯不是存根》中将存根定义为:

    “存根提供对测试过程中进行的呼叫的固定答复,通常通常根本不响应测试中编程的内容。 存根还可以记录有关呼叫的信息,例如电子邮件网关存根,它可以记住“已发送”的消息,或者仅记住“已发送”的消息数量。”

    用一个单词来描述存根非常困难,我可以选择虚拟或伪造,但是有些替换对象称为假人或伪造-也由Martin Fowler描述:

    • 虚拟对象会传递,但从未实际使用过。 通常它们仅用于填充参数列表。
    • 伪对象实际上具有有效的实现,但是通常采取一些捷径,这使它们不适合生产(内存数据库是一个很好的例子)。

    但是,我看到过其他术语“伪造对象”的定义,例如Roy Osherove在《 The Art Of Unit Testing》一书中将伪造对象定义为:

    • 伪造品是一个通用术语,可用于描述存根或模拟对象……因为两者看起来都像真实对象。

    …因此,我和其他许多人一样,倾向于将所有替换对象称为模拟或存根,因为两者之间存在差异,但稍后会更多。

    在测试AddressService时 ,我们需要用存根数据访问对象替换实际的数据访问对象,在这种情况下,它看起来像这样:

    public class StubAddressDao implements AddressDao {
    
      private final Address address;
    
      public StubAddressDao(Address address) {
        this.address = address;
      }
    
      /**
       * @see com.captaindebug.address.AddressDao#findAddress(int)
       */
      @Override
      public Address findAddress(int id) {
        return address;
      }
    }

    注意存根代码的简单性。 它应该易于阅读,可维护,并且不包含任何逻辑,并且需要自己进行单元测试。 编写存根代码后,接下来进行单元测试:

    public class ClassicAddressServiceWithStubTest {
    
      private AddressService instance;
    
      @Before
      public void setUp() throws Exception {
        /* Create the object to test */
        /* Setup data that's used by ALL tests in this class */
        instance = new AddressService();
      }
    
      /**
       * Test method for
       * {@link com.captaindebug.address.AddressService#findAddress(int)}.
       */
      @Test
      public void testFindAddressWithStub() {
    
        /* Setup the test data - stuff that's specific to this test */
        Address expectedAddress = new Address(1, "15 My Street", "My Town",
            "POSTCODE", "My Country");
        instance.setAddressDao(new StubAddressDao(expectedAddress));
    
        /* Run the test */
        Address result = instance.findAddress(1);
    
        /* Assert the results */
        assertEquals(expectedAddress.getId(), result.getId());
        assertEquals(expectedAddress.getStreet(), result.getStreet());
        assertEquals(expectedAddress.getTown(), result.getTown());
        assertEquals(expectedAddress.getPostCode(), result.getPostCode());
        assertEquals(expectedAddress.getCountry(), result.getCountry());
      }
    
      @After
      public void tearDown() {
        /*
         * Clear up to ensure all tests in the class are isolated from each
         * other.
         */
      }
    }

    请注意,在编写单元测试时,我们的目标是清晰。 通常会犯一个错误,就是认为测试代码不如生产代码,从而导致测试代码更加混乱且难以辨认。 单元测试的艺术中的 Roy Osherove提出了这样的想法,即测试代码应比生产代码更具可读性。 明确的测试应遵循以下基本的线性步骤:

    1. 创建被测对象。 在上面的代码中,这是在setUp()方法中完成的,因为我正在对所有(一个)测试使用相同的被测对象。
    2. 设置测试。 这是在测试方法testFindAddressWithStub()中完成的,因为测试中使用的数据特定于该测试。
    3. 运行测试
    4. 撕毁测试。 这样可以确保测试彼此隔离,并且可以按任何顺序运行。

    使用简单的存根会产生将AddressService与外界隔离和快速运行测试的两个好处。

    这种测试有多脆? 如果您的要求改变了,那么测试和存根就会改变–毕竟不是那么脆弱吗?

    作为比较,我的下一个博客使用EasyMock重写了该测试。

    参考: 定期的单元测试和存根-来自JCG合作伙伴 Captain Debug博客上的 测试技术4

    相关文章 :


    翻译自: https://www.javacodegeeks.com/2011/11/regular-unit-tests-and-stubs-testing.html

    展开全文
  • 它基于我使用一种非常常见的模式从数据库检索地址的简单方案: …并且我提出了这样的想法,即任何包含任何逻辑的类实际上都需要单元测试。 在其中,我包括了我的数据访问对象DAO,它更喜欢对此类进行集成测试...

    存根类 测试代码 java

    我的上一个博客是有关测试代码的方法以及讨论您做什么和不必进行测试的方法的一系列博客中的第三篇。 它基于我使用一种非常常见的模式从数据库检索地址的简单方案:

    …并且我提出了这样的想法,即任何不包含任何逻辑的类实际上都不需要单元测试。 在其中,我包括了我的数据访问对象DAO,它更喜欢对此类进行集成测试以确保其与数据库协同工作。

    今天的博客涵盖编写常规或经典的单元测试,该测试使用存根对象强制实现测试主题隔离。 我们将要测试的代码再次是AddressService

    @Component
    public class AddressService {
    
      private static final Logger logger = LoggerFactory.getLogger(AddressService.class);
    
      private AddressDao addressDao;
    
      /**
       * Given an id, retrieve an address. Apply phony business rules.
       * 
       * @param id
       *            The id of the address object.
       */
      public Address findAddress(int id) {
    
        logger.info("In Address Service with id: " + id);
        Address address = addressDao.findAddress(id);
    
        address = businessMethod(address);
    
        logger.info("Leaving Address Service with id: " + id);
        return address;
      }
    
      private Address businessMethod(Address address) {
    
        logger.info("in business method");
    
        // Apply the Special Case Pattern (See MartinFowler.com)
        if (isNull(address)) {
          address = Address.INVALID_ADDRESS;
        }
    
        // Do some jiggery-pokery here....
    
        return address;
      }
    
      private boolean isNull(Object obj) {
        return obj == null;
      }
    
      @Autowired
      @Qualifier("addressDao")
      void setAddressDao(AddressDao addressDao) {
        this.addressDao = addressDao;
      }
    }

    迈克尔·费瑟(Michael Feather)的书《有效地使用旧版代码》指出,在以下情况下,测试不是单元测试:

    1. 它与数据库对话。
    2. 它通过网络进行通信。
    3. 它涉及文件系统。
    4. 您必须对环境做一些特殊的事情(例如编辑配置文件)才能运行它。

    为了遵守这些规则,您需要将被测对象与系统的其余部分隔离开来,这就是存根对象的所在。存根对象是注入到您的对象中的对象,用于在测试情况下替换实际对象。 马丁·福勒(Martin Fowler)在他的论文《 莫克斯不是存根》中将存根定义为:

    “存根提供对测试过程中进行的呼叫的固定答复,通常根本不响应为测试编程的内容之外的任何内容。 存根还可以记录有关呼叫的信息,例如电子邮件网关存根,它可以记住“已发送”的消息,或者仅记住“已发送”的消息数量。”

    用一个单词来描述存根非常困难,我可以选择虚拟或伪造,但是有些替换对象称为假人或伪造,也由Martin Fowler描述:

    • 虚拟对象会传递,但从未实际使用过。 通常它们仅用于填充参数列表。
    • 伪对象实际上具有有效的实现,但是通常采取一些捷径,这使它们不适合生产(内存数据库就是一个很好的例子)。

    但是,我看到过其他术语“伪造对象”的定义,例如Roy Osherove在《 The Art Of Unit Testing》一书中将伪造对象定义为:

    • 伪造品是一个通用术语,可用于描述存根或模拟对象……因为两者看起来都像真实对象。

    …因此,我和其他许多人一样,倾向于将所有替换对象称为模拟或存根,因为两者之间存在差异,但稍后会更多。

    在测试AddressService时 ,我们需要用存根数据访问对象替换实际的数据访问对象,在这种情况下,它看起来像这样:

    public class StubAddressDao implements AddressDao {
    
      private final Address address;
    
      public StubAddressDao(Address address) {
        this.address = address;
      }
    
      /**
       * @see com.captaindebug.address.AddressDao#findAddress(int)
       */
      @Override
      public Address findAddress(int id) {
        return address;
      }
    }

    注意存根代码的简单性。 它应该易于阅读,可维护并且不包含任何逻辑,并且需要自己进行单元测试。 编写存根代码后,接下来进行单元测试:

    public class ClassicAddressServiceWithStubTest {
    
      private AddressService instance;
    
      @Before
      public void setUp() throws Exception {
        /* Create the object to test */
        /* Setup data that's used by ALL tests in this class */
        instance = new AddressService();
      }
    
      /**
       * Test method for
       * {@link com.captaindebug.address.AddressService#findAddress(int)}.
       */
      @Test
      public void testFindAddressWithStub() {
    
        /* Setup the test data - stuff that's specific to this test */
        Address expectedAddress = new Address(1, "15 My Street", "My Town",
            "POSTCODE", "My Country");
        instance.setAddressDao(new StubAddressDao(expectedAddress));
    
        /* Run the test */
        Address result = instance.findAddress(1);
    
        /* Assert the results */
        assertEquals(expectedAddress.getId(), result.getId());
        assertEquals(expectedAddress.getStreet(), result.getStreet());
        assertEquals(expectedAddress.getTown(), result.getTown());
        assertEquals(expectedAddress.getPostCode(), result.getPostCode());
        assertEquals(expectedAddress.getCountry(), result.getCountry());
      }
    
      @After
      public void tearDown() {
        /*
         * Clear up to ensure all tests in the class are isolated from each
         * other.
         */
      }
    }

    请注意,在编写单元测试时,我们的目标是清晰。 通常会犯一个错误,就是认为测试代码不如生产代码,从而导致测试代码更加混乱且难以辨认。 单元测试的艺术中的 Roy Osherove提出了这样的想法,即测试代码应比生产代码更具可读性。 明确的测试应遵循以下基本的线性步骤:

    1. 创建被测对象。 在上面的代码中,这是在setUp()方法中完成的,因为我对所有(一个)测试都使用了相同的被测对象。
    2. 设置测试。 这是在测试方法testFindAddressWithStub()中完成的,因为测试中使用的数据特定于该测试。
    3. 运行测试
    4. 撕毁测试。 这样可以确保测试相互隔离,并且可以按任何顺序运行。

    使用简单的存根会产生将AddressService与外界隔离和快速运行测试的两个好处。

    这种测试有多脆? 如果您的要求改变了,那么测试和存根就会改变–毕竟不是那么脆弱吗?

    作为比较,我的下一个博客使用EasyMock重写了该测试。

    参考:来自Captain Debug博客的 JCG合作伙伴 常规单元测试和存根-测试技术4

    相关文章 :


    翻译自: https://www.javacodegeeks.com/2011/11/regular-unit-tests-and-stubs-testing.html

    存根类 测试代码 java

    展开全文
  • Laravel减轻了许多Web项目中使用的常见任务,从而减轻了开发过程中痛苦,例如: 。 。 用于和存储多个后端。 富有表现力,直观数据库不可知。 。 。 Laravel易于访问,功能强大,并提供大型,...
  • 整个K8S体系涉及到的技术众多,包括存储、网络、安全、监控、日志、DevOps、微服务等,很多刚接触K8S初学者,都会感到无从下手,为了能让大家系统地学习,克服这些技术难点,推出了这套K8S架构师课程。Kubernetes...
  • MyEclipse,Deamweare,选择SQLserver作为后台的数据库,选择JAVA、JSP、JavaScript、Html作为应用程序开发工具,运用Tomcat服务器技术,整个系统完全基于B/S (Browser/Server)模式进行设计。 1、Tomcat应用服务器 ...
  • 开发过程中可以提升性能八大处

    千次阅读 2013-04-30 15:50:25
    数据库访问低效、框架配置错误、内存使用过度、网页臃肿,以及遵循常见Web性能最佳实践都是应用开发中常见的、影响应用性能的主要陷阱 。技术性能公司Computeware从实际案例总结了贯穿应用始终的八大影响应用性能...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 220
精华内容 88
关键字:

常见的数据库访问技术不包括