- 浏览: 628087 次
- 性别:
- 来自: 北京
最新评论
动机
曾经使用许多方法在数据库和目标代码之间传输数据。从手动编码的SQL到JDO,然后再到EJB,我从未找到一种特别喜欢的方法。自从采用测试驱动开发(TDD)作为指导原则以来,这种不满情绪变得更加强烈。
单元测试的障碍应尽可能少。在关系数据库中,障碍的范围从外部依赖(数据库在运行吗?)到保持关系模型和对象模型同步的速度。由于这些原因,保持数据库访问代码与核心对象模型分离且无需涉及真实数据库而进行尽可能多的测试是很重要的。
通常这会导致我们进入下面两种模式之一。第一种是具体化所有访问域对象的数据以及数据与单独类或接口之间的关系。这就是典型的能够检索、编辑、删除和添加域实体的数据存储对象。这在单元测试中是最容易模拟出来的,但趋向于把域模型对象作为不带有任何关系行为的纯数据对象。直接从父对象访问子记录是最理想的,而不是将父对象处理为第三方类来决定子记录。
其他方法已经使访问接口的域对象进入数据映射层(一种la Martin Fowler的数据映象模式)。这具有推动域模型中的对象关系的优点,在域模型中,对象关系型接口只需表达一次即可。使用域模型的类不支持持久性机制,因为它本身内在化到域模型中。这使代码集中在设法解决的业务问题,而很少关注对象关系型映射机制。
我的当前项目涉及到处理大量的棒球统计数据,并使用这些数据进行模拟。因为数据已经在关系数据库中,所以对于我来说,有机会开发Hibernate对象关系型映射系统。我曾对Hibernate有很深刻的印象,但我遇到的一个问题是,在使用Hibernate进行单元测试的数据映射时,设法插入一个间接层。该附加层非常脆弱,编写起来感到非常困难。实际部署版本简单地通过了特定于Hibernate的实现。更坏的情况是,模拟版本比真正的“产品级”版本更复杂,只因为模拟版本里没有基本对象存储器和带有Hibernate的映射。
我也使用很多复杂的Hibernate查询,想要对应用程序的重要部分进行单元测试。然而,对活动的数据库进行测试不是好主意,因为这几乎总是产生维护问题。另外,由于测试最好互相独立,在测试上下文数据中使用相同的主键意味着必须在每次测试前创建代码来清理数据库,当涉及到大量关系时就成为一个实际问题。
通过使用HSQLDB和Hibernate强大的模式生成工具,能够对应用程序映射层进行单元测试,并在对象查询中找到不计其数的bug,这在以前手工测试时是做不到的。利用下面的技术概述,可以在开发过程中对整个应用程序进行测试,并且在测试有效区域内没有损害。
设置HSQLDB
以前使用HSQLDB 1.7.3.0 版。为了使用数据库的内存版本,需要激活org.hsqldb.jdbcDriver的静态加载程序。当获得JDBC连接时,就可以使用JDBC url例如jdbc:hspldb:mem:yourdb,这里’yourdb’就是想要使用的内存数据库的名称。
因为使用Hibernate (3.0 beta 4),所以我几乎无需接触实际活动的JDBC对象。相反,我可以让Hibernate完成很多繁重的任务,包括从Hibernate映射文件中自动创建数据库模式。因为Hibernate创建自身专有的连接池,所以它会基于TestSchema类中的配置代码自动加载HSQLDB JDBC驱动程序。下面就是该类的静态的初始化程序。
public class TestSchema { static { Configuration config = new Configuration(). setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"). setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver"). setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:baseball"). setProperty("hibernate.connection.username", "sa"). setProperty("hibernate.connection.password", ""). setProperty("hibernate.connection.pool_size", "1"). setProperty("hibernate.connection.autocommit", "true"). setProperty("hibernate.cache.provider_class", "org.hibernate.cache.HashtableCacheProvider"). setProperty("hibernate.hbm2ddl.auto", "create-drop"). setProperty("hibernate.show_sql", "true"). addClass(Player.class). addClass(BattingStint.class). addClass(FieldingStint.class). addClass(PitchingStint.class); HibernateUtil.setSessionFactory(config.buildSessionFactory()); }
Hibernate提供了许多不同的方式来配置该框架,包括程序方面的配置。上述代码设置了连接池。注意,使用HSQLDB的内存数据库需要用户名'sa’。还样要确保指定一个空格作为口令。为了启动Hibernate的自动模式生成功能,需设置hibernate.hbm2ddl.auto属性为’creat-drop’。
实际测试 我的项目是处理将大量的棒球数据,所以我添加了四个进行映射的类(Player、PintchingStint、,BattingSint和FieldStint)。最后创建Hibernate的会话工厂,并将其插入HibernateUtil类,该类只为Hibernate会话的整个应用程序提供一个访问方法。HibernateUtil的代码如下:
import org.hibernate.*; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static SessionFactory factory; public static synchronized Session getSession() { if (factory == null) { factory = new Configuration().configure().buildSessionFactory(); } return factory.openSession(); } public static void setSessionFactory(SessionFactory factory) { HibernateUtil.factory = factory; } }
因为所有代码(经过单元测试的产品级代码)都是从HibernateUtil获取Hibernate会话,所以能在同一个位置对其进行配置。为了对代码的第一位进行单元测试而访问TestSchema类将会激活静态初始化程序,该程序将安装Hibernate并且将测试SessionFactory插入到HibernateUtil中。对于产品级代码,可以使用标准hibernate.cfg.xml配置机制来初始化 SessionFactory。
那么单元测试中的外部特征是什么?下面的测试代码片段是用来检查逻辑的,决定运动员在棒球联盟比赛中是哪个位置的人选:
public void testGetEligiblePositions() throws Exception { Player player = new Player("playerId"); TestSchema.addPlayer(player); FieldingStint stint1 = new FieldingStint("playerId", 2004, "SEA", Position.CATCHER); stint1.setGames(20); TestSchema.addFieldingStint(stint1); Set<Position> positions = player.getEligiblePositions(2004); assertEquals(1, positions.size()); assertTrue(positions.contains(Position.CATCHER)); }
第一次创建新Player实例并通过addPlayer()方法添加到TestSchema中。必须首先完成此步骤,因为FidldStint类和Player类之间有外键关系。如果不首先添加该实例,在设法添加FieldingStint时将会出现外键约束违例。一旦测试上下文就位,就可以测试getEligiblePositions()方法来检索校正数据。下面是在TsetSchema中addPlayer()方法的代码。您将注意到使用Hibernate而不是bare-metal JDBC代码:
public static void addPlayer(Player player) { if (player.getPlayerId() == null) { throw new IllegalArgumentException("No primary key specified"); } Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); try { session.save(player, player.getPlayerId()); transaction.commit(); } finally { session.close(); } }
在单元测试中最重要的就是要保持测试实例是独立的。因为该方法仍然涉及数据库,所以需要一种方法在每个测试实例之前清理数据库。在我的数据库架构中有四个表,所以我在TestSchemaz上编写了reset()方法,该方法从使用JDBC的表中删除所有行。注意,因为HSQLDB能识别外键,删除表的顺序是很重要的,下面是代码:
public static void reset() throws SchemaException { Session session = HibernateUtil.getSession(); try { Connection connection = session.connection(); try { Statement statement = connection.createStatement(); try { statement.executeUpdate("delete from Batting"); statement.executeUpdate("delete from Fielding"); statement.executeUpdate("delete from Pitching"); statement.executeUpdate("delete from Player"); connection.commit(); } finally { statement.close(); } } catch (HibernateException e) { connection.rollback(); throw new SchemaException(e); } catch (SQLException e) { connection.rollback(); throw new SchemaException(e); } } catch (SQLException e) { throw new SchemaException(e); } finally { session.close(); } }
当确定在Hibernate 3.0中进行大量删除操作时,应该能从应用程序中删除直接JDBC的最后一位。到此时为止,必须获取数据库连接并向数据库直接提交SQL。 在确保没有关闭连接的情况下,为了释放资源,只关闭会话就足够了。出于手工编写许多JCBC代码来进行开发的习惯,第一个版本关闭了JDBC连接。因为通过配置Hibernate创建的连接池只带有一个链接,在第一个之后就完全破坏了测试。一定要注意这种情况! 既然在测试类运行时(设想运行所有的测试实例)不能确定数据库的状态,应该在setUp()方法中包含数据库清除,如下所示:
public void setUp() throws Exception { TestSchema.reset(); }结束语
在使用像Hibernate这种复杂的O/R映射程序时,必须能够测试实际存在(real-live)的RDBMS,而不会发生任何针对已部署数据库的争论。虽然Hibernate有内置模式生成工具,让此类测试特别简单,但是在这里展示的例子并不排除Hibernate,并且可能与JDO或TopLink一起运行。使用上面描述的设置,您不必离开舒适的IDE环境,但仍然可以对代码进行大量测试。
April 2005
Discussion
The Motivation
I've used lots of methods to transform data between databases and object code. From hand-coded SQL to JDO to EJB. I've never found a method I liked particularly well. This distaste has become especially acute since adopting test-driven development (TDD) as a guiding philosophy.
Unit-testing should have as few barriers as possible. For relational databases those barriers range from external dependencies (is the database running?) to speed to keeping the relational schema synchronized with your object model. For these reasons it is vital to keep database access code away from the core object model and to test as much as possible without touching a real database.
This has often led me to one of two patterns. The first is externalizing all data access to domain objects and their relationships to separate classes or interfaces. These are typically data store objects that can retrieve, edit, delete and add domain entities. This is the easiest to mock-out for unit-testing, but tends to leave your domain model objects as data-only objects with little or no related behavior. Ideally access to child records would be directly from the parent object rather than handing the parent object to some third-party class to determine the children.
The other method has been to have the domain objects have access to an interface into the data-mapping layer a la Martin Fowler’s Data Mapper pattern. This has the advantage of pushing object relationships inside the domain model where the object-relational interface can be expressed once. Classes that use the domain model are unaware of the persistence mechanism because it is internalized into the domain model itself. This keeps your code focused on the business problem you are trying to solve and less about the object-relational mapping mechanism.
My current project involves crunching a number of baseball statistics and running simulations with the data. Since the data was already in a relational database it was a chance for me to explore the Hibernate object-relational mapping system. I have been very impressed with Hibernate, but I ran into the problem was trying to insert a layer of indirection while using Hibernate as my data mapper for unit-testing. The extra layer was so flimsy that it felt embarrassing to write it. The real deployed version was simply a pass-through to a Hibernate-specific implementation. Even worse, the mock versions had more complexity in them than the real "production" version simply because they didn't have some of the basic object storage and mapping that came with Hibernate.
I also had enough complex Hibernate query usage that I wanted to unit-test this significat portion of the application. However, testing against a ‘live’ database is a bad idea, because it almost invariably introduces a maintenance nightmare. In addition, since tests are best when they are independent from each other, using the same obvious primary keys in test fixture data means you have to create code to clean the database before each test case, which is a real problem when lots of relationships are involved
By using HSQLDB and Hibernate's powerful schema-generation tool I was able to unit-test the mapping layer of the application and find numerous bugs in my object queries I would not have found as easily by manual testing. With the techniques outlines below I was able unit-test my entire application during development with no compromises in test coverage.
Setting up HSQLDB
I used version 1.7.3.0 of HSQLDB. To use an in-memory version of the database you need to invoke the static loader for the org.hsqldb.jdbcDriver. Then when you get a JDBC connection you use JDBC url such as jdbc:hsqldb:mem:yourdb where 'yourdb' is the name of the in-memory database you want to use.
Since I'm using Hibernate (3.0 beta 4), I hardly ever need to touch real-live JDBC objects. Instead I can let Hibernate do the heavy lifting for me--including automatically creating the database schema from my Hibernate mapping files. Since Hibernate creates its own connection pool it will automatically load the HSQLDB JDBC driver based on the configuration code lives in a class called TestSchema. Below is the static initializer for the class.
public class TestSchema { static { Configuration config = new Configuration(). setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect"). setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver"). setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:baseball"). setProperty("hibernate.connection.username", "sa"). setProperty("hibernate.connection.password", ""). setProperty("hibernate.connection.pool_size", "1"). setProperty("hibernate.connection.autocommit", "true"). setProperty("hibernate.cache.provider_class", "org.hibernate.cache.HashtableCacheProvider"). setProperty("hibernate.hbm2ddl.auto", "create-drop"). setProperty("hibernate.show_sql", "true"). addClass(Player.class). addClass(BattingStint.class). addClass(FieldingStint.class). addClass(PitchingStint.class); HibernateUtil.setSessionFactory(config.buildSessionFactory()); }
Hibernate provides a number of different ways to configure the framework, including programmatic configuration. The code above sets up the connection pool. Note that the user name 'sa' is required to use HSQLDB's in-memory database. Also be sure to specify a blank as the password. To enable Hibernate's automatic schema generation set the hibernate.hbm2ddl.auto property to 'create-drop'.
Testing In Practice
My project is crunching a bunch of baseball statistics so I add the four classes that I'm mapping ( Player, PitchingStint, BattingStint and FieldingStint). Finally I create a Hibernate SessionFactory and insert it into the HibernateUtil class which simply provides a single access method for my entire application for Hibernate sessions. The code for the HibernateUtil is below:
import org.hibernate.*; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static SessionFactory factory; public static synchronized Session getSession() { if (factory == null) { factory = new Configuration().configure().buildSessionFactory(); } return factory.openSession(); } public static void setSessionFactory(SessionFactory factory) { HibernateUtil.factory = factory; } }
Since all of my code (production code as well as unit-tests) get their Hibernate sessions from the HibernateUtil I can configure it in one place. For unit-tests the first bit of code to access the TestSchema class will invoke the static initializer which will setup Hibernate and inject the test SessionFactory into the HibernateUtil. For production code the SessionFactory will be initialized lazily using the standard hibernate.cfg.xml configuration mechanism.
So what does this look like in the unit-tests? Below is a snippet of a test that checks the the logic for determining what positions a player is eligible to play at for a fantasy baseball league:
public void testGetEligiblePositions() throws Exception { Player player = new Player("playerId"); TestSchema.addPlayer(player); FieldingStint stint1 = new FieldingStint("playerId", 2004, "SEA", Position.CATCHER); stint1.setGames(20); TestSchema.addFieldingStint(stint1); Set<Position> positions = player.getEligiblePositions(2004); assertEquals(1, positions.size()); assertTrue(positions.contains(Position.CATCHER)); }
I first create a new Player instance and add it to the TestSchema via the addPlayer() method. This step must occur first because the FieldingStint class has a foreign-key relationship to the Player class. If I didn't add this instance first I would get a foreign-key constraint violation when I try to add the FieldingStint. Once the test-fixture is in place I can test the getEligiblePositions() method to see that it retrieves the correct data. Below is the code for the addPlayer() method in the TestSchema. You will notice that Hibernate is used instead of bare-metal JDBC code:
}
public static void addPlayer(Player player) { if (player.getPlayerId() == null) { throw new IllegalArgumentException("No primary key specified"); } Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); try { session.save(player, player.getPlayerId()); transaction.commit(); } finally { session.close(); } }
One of the most important things in unit-testing is to keep your test-cases isolated. Since this method still involves a database, you need a way to clean your database prior to each test case. I have four tables in my schema so I wrote a reset() method on the TestSchema that removes all rows from the tables using JDBC. Note because HSQLDB knows about foreign keys, the order in which the tables are deleted is important. Here is the code:
public static void reset() throws SchemaException { Session session = HibernateUtil.getSession(); try { Connection connection = session.connection(); try { Statement statement = connection.createStatement(); try { statement.executeUpdate("delete from Batting"); statement.executeUpdate("delete from Fielding"); statement.executeUpdate("delete from Pitching"); statement.executeUpdate("delete from Player"); connection.commit(); } finally { statement.close(); } } catch (HibernateException e) { connection.rollback(); throw new SchemaException(e); } catch (SQLException e) { connection.rollback(); throw new SchemaException(e); } } catch (SQLException e) { throw new SchemaException(e); } finally { session.close(); } }
When bulk deletes become finalized in Hibernate 3.0 we should able to remove this last bit of direct JDBC from our application. Until then we have to get a Connection and issue direct SQL to the database.
Be sure not to close your Connection, closing the Session is sufficient for resource cleanup. Out of habits developed from writing lots of hand-crafted JDBC code, the first version closed the JDBC Connection. Since I configured Hibernate to create a connection pool with only one Connection I completely torpedoed any tests after the first one.Be sure to watch out for this!
Since you can never be sure what state the database may be in when your test class is running (imagine running all of your test cases), you should include database cleanup in your setUp() methods like so:
public void setUp() throws Exception { TestSchema.reset(); }
Conclusion
Being able to test against a real-live RDBMS without all of the hassles of trying to run tests against your deployed database is essential, even when working with sophisticated O/R mappers like Hibernate. The example I showed here is not exclusive to Hibernate and could probably be made to work with JDO or TopLink, though Hibernate makes this kind of testing particularly easy since it has a built-in schema generation tool. With a setup like the one described above you don't ever have to leave the comfort of your IDE and still have extensive test coverage over your code.
发表评论
-
grafana+mysql 页面设计
2019-02-25 08:51 0前提 1。主要是SELECT 。 2。使用mysql ... -
测试用例到底怎么才值的写
2016-04-30 10:32 0有个方法是这样的 public function ... -
postman cookies登陆设置
2016-04-28 09:30 2056必须登陆才能测试的接口如何测试? 打开这个开关就可以共用coo ... -
将png 切成ios android能用的格式
2016-04-28 01:24 741由于要求不高找了个在线切图的工具 http://images. ... -
如何在原有系统中加入功能(一数据库)
2016-04-24 11:06 821第一步想办法把建表语句导入一powerdesginer ... -
关于四维的问题
2016-04-22 14:14 1183知乎:为什么人类想象不出四维的空间? https://www. ... -
油猴对抗一般广告
2012-11-14 00:07 1886看小说 好多好多的广告是必然的.. 所以 去掉iframe 去 ... -
油猴对抗google抽疯
2012-10-23 16:25 1807http://www.iteye.com/topic/1127 ... -
2010-5-26工作日志
2010-05-26 15:24 1435上午写测试用例发现很多jar包没有 但项目还能用.....好鬼 ... -
工作日志20090331
2009-03-31 10:34 1896大约五个月的一个项目看样子快要完成了 项目进度非常的快. 但客 ... -
工作日志20081106(一个VBA的宏)
2008-11-06 16:31 1627本宏是用来把h列的所有相临相同的元素合并用的...... 并非 ... -
工作日志20081106
2008-11-06 16:14 1181var rooturl_String = new String ... -
20080909工作日志(网页版翻译)
2008-09-09 14:14 2341写了一个用google翻译的小工具... 很粗糙... & ... -
DBA的工作
2008-07-01 20:52 2203DBA被分到总公司名下的另一家子公司 我作flash也很长时间 ... -
工作日志20080530
2008-05-30 09:23 0又是需求讨论。 三个病人。。。。 我哑的不行, 另两个吃着感冒 ... -
工作日志200080327
2008-03-27 12:43 2018今天主要的工作: 1,上china-pub订书(SSH)下个月 ... -
工作日志20080218
2008-02-18 18:00 64好 的ant 是长出来的 (前略) 刚刚发现ant过不去j ... -
来看看什么叫年度工作总结吧(工作日志20080130)
2008-01-30 11:26 3621http://docs.google.com/Present ... -
工作日志200080123
2008-01-23 08:04 2035旧项目上线 新项目启动 大统一的业务流..... 我真不知 ... -
工作日志20071023(MySQL的用法章)
2007-10-23 10:22 2512今天要花一天时间来玩MySQL 1.命令行 2.得到连接 3. ...
相关推荐
HSQLDB与Hibernate配合良好,适合进行单元测试和集成测试,因为它允许在测试完成后快速清除数据库状态。 4. **整合过程**: 在这个测试项目中,Spring和Hibernate通常会通过Spring的HibernateTemplate或者...
单元测试是针对程序模块的最小可测试单元进行验证,例如一个方法或一个类。它的目的是确保代码的每个部分都能按照预期工作,独立于其他部分。在Java中,JUnit是最常用的单元测试框架,而Hibernate则可以提供数据库...
在本篇《junit学习(十)——Spring与Hibernate整合的单元测试》中,我们将探讨如何在Java开发中,利用JUnit进行Spring和Hibernate框架的集成测试。单元测试是软件开发中的重要环节,它能帮助开发者确保代码的质量和...
**HSQLDB(HyperSQL Database)详解** HSQLDB,全称HyperSQL数据库管理系统,是一款开源、轻量级、高性能的关系型数据库系统。...通过深入学习和实践,我们可以充分利用HSQLDB提供的功能,提升我们的数据库管理能力。
此外,可以利用H2或HSQLDB这样的内存数据库来快速创建临时测试数据库。 在结合Spring和Hibernate进行测试时,有几种常见的测试策略: 1. **单元测试**:专注于单一的函数或方法,通常不涉及数据库交互。你可以使用...
它简化了测试数据库连接的配置,使得测试数据的插入和管理更加便捷,同时利用DbUnit进行数据验证。此外,它还提供了对Hibernate会话的自动化管理,帮助测试与数据库映射的Hibernate实体。 对于依赖注入,Unitils...
- **单元测试**: 使用JUnit或TestNG等框架,结合HSQLDB或H2等内存数据库进行单元测试。 - **集成测试**: 检查Hibernate与整个应用系统的集成情况,确保所有组件协同工作正常。 7. **扩展Hibernate** - **拦截器...
3. **Hibernate**:对于数据层的测试,可以使用Hibernate的Session和SessionFactory模拟数据库操作,或者利用HSQLDB等内存数据库进行真实的数据库交互。 【具体步骤】: 1. 创建测试类,并用`@RunWith(SpringRunner...
HSQldb是一个完全用Java编写的开源关系型数据库管理系统(RDBMS),它支持SQL标准并且可以在多种操作系统上运行,包括Windows、...通过深入理解和熟练运用,开发者可以充分利用HSQldb的特性来优化数据管理和处理流程。
1. **JUnit测试框架**:JUnit是一个开源的、基于Java的测试框架,它遵循xUnit测试设计模式,提供断言方法、测试注解和测试套件等功能,帮助程序员进行单元测试。 2. **测试注解**:在纯Java的JUnit测试中,我们通常...
这种配置允许快速地进行单元测试,因为HSQLDB在内存中运行,启动速度快,且易于管理。 **测试案例** 1. **session.get() 与二级缓存** `testSessionGetCache()`方法测试了`Session.get()`方法是否能利用二级缓存...
"livebookstore-with-hsqldb-1.0.zip" 是一个包含此类系统的压缩包,它利用了Spring 2.0框架、UML建模语言以及SSH(Struts、Spring、Hibernate)技术栈,同时还集成了轻量级数据库HSQldb。这个项目为我们提供了深入...
结合JUnit和Mockito,可以对整合后的系统进行单元测试,确保每个组件的正确性。对于Service和DAO层,可以使用内存数据库如HSQLDB来进行快速的集成测试。 9. **部署与优化**: 在实际应用中,需要考虑性能优化,如...
这个项目展示了如何利用JSF框架来构建一个完整的Web应用程序,同时结合Maven进行项目管理和依赖管理,以及使用HSQLDB作为轻量级数据库,JPA(Java Persistence API)进行数据持久化,以及Hibernate作为JPA的实现工具...
【标题】"ProjetoI:使用 Maven、HSQLDB、JPA 和 Hibernate 在博客上实现 JSF" 是一个综合性的 Java 项目,旨在演示如何利用这些技术构建一个功能齐全的博客系统。在这个项目中,开发者将学习到如何整合不同的开源...
4. **单元测试**:编写JUnit测试用例,验证各个组件的功能是否正常工作。 #### 五、总结 通过上述步骤,我们成功地在Web项目中集成了Struts、Hibernate、Log4j以及Spring框架。这种集成不仅提高了应用程序的开发...
SSH是Java开发中常见的三个框架的缩写,分别...开发者可以通过这三个框架的集成,实现模型的业务逻辑、控制层的调度和视图的展示,同时利用Spring的强大功能进行数据访问和事务管理,以及通过Hibernate简化数据库操作。
- 使用JUnit或其他测试工具对业务逻辑进行单元测试,确保代码质量。 6. **优化与扩展** - 可根据需求添加安全框架,如Spring Security,增强应用安全性。 - 结合Maven或Gradle进行项目构建,便于管理和依赖...
使用Hibernate开发应用软件时,一些数据的存储会涉及到比较复杂的商务逻辑,基于JUnit的单元测试无法覆盖所有复杂商务逻辑的检测工作。当软件出现错误时,开发人员通常需要察看保存在数据库中的数据,并以此为依据...