与硒的集成测试

总览

我已经使用了一段时间,遇到了一些似乎可以使生活更轻松的事情。 我以为可以将其作为教程分享,所以我将向您介绍这些部分:

  1. 使用Maven设置Web项目,配置Selenium以在CI上作为集成测试运行
  2. 寻找使用“页面对象”为网站中的页面建模的好方法,以及其他创建受保护的变量的方法。
  3. 使用JPA和Hibernate对数据库执行CRUD操作,并让Maven对它们执行集成测试,而无需进行有时会涉及的任何昂贵且通常没有文档的设置。

这篇文章假定您对Java,Spring,Maven 2和HTML感到满意。 您还需要在计算机上安装Firefox。 本教程旨在以其他方式与技术无关。

创建一个Webapp

首先,我们需要一个webapp进行测试。 使用maven-webapp-archetype创建一个项目,并将其称为“ selenuim-tutorial”。

要运行集成测试(IT),我们将使用Cargo插件。 这将启动和停止Jetty和Tomcat之类的容器。 您可以使用Cargo在一个命令中使用Jetty(默认设置)启动网站,而无需进行任何更改:

mvn cargo:run

并在浏览器中检查它:

http:// localhost:8080 / selenuim-tutorial

您将获得一个没有欢迎文件设置的404,因此将其添加到web.xml文件中:

<welcome-file-list><welcome-file>/index.jsp</welcome-file>
</welcome-file-list>

如果您运行货物:再次运行,您现在将看到“ Hello World!” 由Maven创建的页面。

配置货物

我们可以将Cargo设置为在运行测试之前启动Jetty容器,然后再将其停止。 这将使我们能够启动站点,运行集成测试,然后再将其停止。

<plugin><groupId>org.codehaus.cargo</groupId><artifactId>cargo-maven2-plugin</artifactId><version>1.2.0</version><executions><execution><id>start</id><phase>pre-integration-test</phase><goals><goal>start</goal></goals></execution><execution><id>stop</id><phase>post-integration-test</phase><goals><goal>stop</goal></goals></execution></executions>
</plugin>

您可以使用以下方法测试这项工作:

mvn verify

此时要注意的一件事是Cargo运行在端口8080上。如果您已经有一个进程在该端口上进行侦听,则可能会看到类似以下错误:

java.net.BindException: Address already in use

这可能是因为您已经在该端口上运行了另一个容器。 如果要在CI上运行它(它本身可以在端口8080上运行),则可能需要更改。 将这些行添加到插件设置中:

<configuration><type>standalone</type><configuration><properties><cargo.servlet.port>10001</cargo.servlet.port></properties></configuration>
</configuration>

现在该应用程序将在这里:

http:// localhost:10001 / selenuim-tutorial /

设置集成测试阶段

接下来,我们需要能够运行集成测试。 这需要Maven故障安全插件,并将适当的目标添加到pom中:

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-failsafe-plugin</artifactId><version>2.12</version><executions><execution><id>default</id><goals><goal>integration-test</goal><goal>verify</goal></goals></execution></executions>
</plugin>

默认情况下,Failsafe期望测试匹配模式“ src / test / java / * / * IT.java”。 让我们创建一个测试来证明这一点。 请注意,我尚未从Junit 3.8.1更改过。 我稍后会解释原因。

这是一个基本的,不完整的测试:

package tutorial;import junit.framework.TestCase;public class IndexPageIT extends TestCase {@Overrideprotected void setUp() throws Exception {super.setUp();}@Overrideprotected void tearDown() throws Exception {super.tearDown();}public void testWeSeeHelloWorld() {fail();}
}

测试有效:

mvn verify

您应该看到一个测试失败。

要使用Selenium进行测试,您需要向pom.xml添加测试范围的依赖项:

<dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-firefox-driver</artifactId><version>2.19.0</version><scope>test</scope>
</dependency>

现在,我们可以对测试进行一些更改:

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;…private URI siteBase;private WebDriver drv;@Overrideprotected void setUp() throws Exception {super.setUp();siteBase = new URI("http://localhost:10001/selenuim-tutorial/");drv = new FirefoxDriver();}...public void testWeSeeHelloWorld() {drv.get(siteBase.toString());assertTrue(drv.getPageSource().contains("Hello World"));}

稍后我们将删除这些硬编码值。

再次运行:

mvn verify

您应该不会看到任何故障。 您将拥有一个挥之不去的Firefox。 它不会关闭。 运行此测试100次,您将运行100个Firefox。 这将很快成为一个问题。 我们可以通过在测试中添加以下初始化块来解决此问题:

{Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {drv.close();}});}

自然,如果我们创建另一个测试,我们将很快违反DRY原则。 我们将在下一部分中讨论该问题,并查看需要数据库连接时发生的情况,以及其他一些方法来确保您的测试易于编写和维护。

Spring语境

在前面的示例中,应用程序的URI和使用的驱动程序都经过了硬编码。 假设您熟悉Spring上下文,那么更改这些上下文就很简单了。 首先,我们将添加正确的依赖项:

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>3.1.1.RELEASE</version><scope>test</scope>
</dependency>

这将使我们能够使用和应用程序上下文注入依赖项。 但是我们还需要正确的Junit运行程序来测试它,可以在spring-test软件包中找到它:

<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>3.1.1.RELEASE</version><scope>test</scope>
</dependency>

现在,我们可以更新测试以使用它。 首先,我们需要创建src / test / resources / applicationContext-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd"><bean id="siteBase" class="java.net.URI"><constructor-arg value="http://localhost:10001/selenuim-tutorial/" /></bean><bean id="drv" class="org.openqa.selenium.firefox.FirefoxDriver" destroy-method="quit"/>
</beans>

Spring完成后将清除浏览器,因此我们可以从AbstractIT中删除关闭钩子。 这比让测试用例执行此操作更健壮。

弹簧测试不适用于JUnit 3,它至少需要JUnit 4.5。 让我们在pom.xml中更新到版本4.10:

<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.10</version><scope>test</scope>
</dependency>

最后,我们需要更新测试以同时使用Spring和JUnit 4.x:

package tutorial;import static org.junit.Assert.assertTrue;import java.net.URI;import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/applicationContext-test.xml" })
public class IndexPageIT {@Autowiredprivate URI siteBase;@Autowiredprivate WebDriver drv;@Testpublic void testWeSeeHelloWorld() {
...

这些更改将配置从硬编码值转移到XML配置。 现在,我们可以将要测试的位置更改为例如其他主机,并更改我们正在使用的Web驱动程序,这留给用户练习。

关于浏览器的快速说明。 我发现浏览器更新后,测试通常会开始失败。 似乎有两种解决方案:

  • 升级到最新版本的Web驱动程序。
  • 不要升级浏览器。

我出于安全原因怀疑,在大多数情况下,第一种选择是最好的

抽象IT

当前,您需要复制IoC的所有代码。 一个简单的重构可以解决这个问题。 我们将为所有测试和上拉通用功能创建一个超类。 出于重构的目的,继承使用的是继承,而不是合成。

package tutorial;import java.net.URI;import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/applicationContext-test.xml" })
public abstract class AbstractIT {@Autowiredprivate URI siteBase;@Autowiredprivate WebDriver drv;public URI getSiteBase() {return siteBase;}public WebDriver getDrv() {return drv;}
}
package tutorial;import static org.junit.Assert.assertTrue;import org.junit.Test;public class IndexPageIT extends AbstractIT {@Testpublic void testWeSeeHelloWorld() {getDrv().get(getSiteBase().toString());assertTrue(getDrv().getPageSource().contains("Hello World"));}
}

页面对象

“页面对象”是封装页面的单个实例并为该实例提供程序化API的对象。 基本页面可能是:

package tutorial;import java.net.URI;import org.openqa.selenium.WebDriver;public class IndexPage {/*** @param drv*            A web driver.* @param siteBase*            The root URI of a the expected site.* @return Whether or not the driver is at the index page of the site.*/public static boolean isAtIndexPage(WebDriver drv, URI siteBase) {return drv.getCurrentUrl().equals(siteBase);}private final WebDriver drv;private final URI siteBase;public IndexPage(WebDriver drv, URI siteBase) {if (!isAtIndexPage(drv, siteBase)) { throw new IllegalStateException(); }this.drv = drv;this.siteBase = siteBase;}
}

请注意,我已经提供了一个静态方法来返回我们是否在索引页上,并且已经对其进行了注释(对于这种自填充方法,这是不必要的)。 页面对象形成一个API,值得记录。 您还将看到,如果URL不正确,我们将引发异常。 值得考虑使用什么条件来识别页面。 任何可能更改的内容(例如页面标题,可能会在不同语言之间更改)都是一个糟糕的选择。 不变的东西和机器可读的东西(例如页面的路径)是不错的选择。 如果要更改路径,则需要更改测试。

现在让我们自己制造一个问题。 我想将其添加到index.jsp,但是生成HTML无法解析:

<% throw new RuntimeException(); %>

相反,我们将创建一个新的servlet,但是首先我们需要将servlet-api添加到pom.xml中:

<dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope>
</dependency>
package tutorial;import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class IndexServlet extends HttpServlet {private static final long serialVersionUID = 1L;protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {throw new RuntimeException();}
}

将其添加到web.xml并删除现在不必要的欢迎页面:

<!DOCTYPE web-app PUBLIC"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN""http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app><servlet><servlet-name>IndexServlet</servlet-name><servlet-class>tutorial.IndexServlet</servlet-class></servlet><servlet-mapping><servlet-name>IndexServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
</web-app>

更新IndexPageIT:

@Testpublic void testWeSeeHelloWorld() {getDrv().get(getSiteBase().toString());new IndexPage(getDrv(), getSiteBase());}

再次运行测试。 它通过了。 这可能不是您想要的行为。 Selenium没有提供通过WebDriver实例检查HTTP状态代码的方法。 容器之间的默认错误页面也没有足够一致(例如,与在Tomcat上运行时所发生的情况进行比较); 我们无法对错误页面的内容进行假设以判断是否发生错误。

我们的索引页面当前不具备任何机器可读功能,因此无法从错误页面中分辨出来。

要整理,请修改servlet以显示index.jsp:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {getServletContext().getRequestDispatcher("/index.jsp").forward(request, response);}

当前index.jsp有点太简单了。 在index.jsp旁边创建一个名为create-order.jsp的新页面,并在index.jsp上创建指向该页面的链接。 我们可以为订单页面创建一个新类,并创建一个将我们从索引页面导航到订单页面的方法。

将以下内容添加到index.jsp中:

<a href="create-order.jsp">Create an order</a>

create-order.jsp现在可以为空。 我们还可以为其创建一个页面对象:

package tutorial;import java.net.URI;import org.openqa.selenium.WebDriver;public class CreateOrderPage {public static boolean isAtCreateOrderPage(WebDriver drv, URI siteBase) {return drv.getCurrentUrl().equals(siteBase.toString() + "create-order.jsp");}private final WebDriver drv;private final URI siteBase;public CreateOrderPage(WebDriver drv, URI siteBase) {if (!isAtCreateOrderPage(drv, siteBase)) { throw new IllegalStateException(); }this.drv = drv;this.siteBase = siteBase;}
}

将以下依赖项添加到pom.xml中,这将为我们提供一些有用的注释:

<dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-support</artifactId><version>2.19.0</version><scope>test</scope>
</dependency>

我们现在可以充实IndexPage了:

@FindBy(css = "a[href='create-order.jsp']")private WebElement createOrderLink;public IndexPage(WebDriver drv, URI siteBase) {if (!isAtIndexPage(drv, siteBase)) { throw new IllegalStateException(); }PageFactory.initElements(drv, this);this.drv = drv;this.siteBase = siteBase;}

对PageFactory.initElements的此调用将填充带有@FindBy注释的字段,该对象具有与网页上的元素匹配的对象。 请注意,使用CSS选择器是为了以不太可能更改的方式定位链接。 其他方法包括使用链接文本匹配页面上的元素(可能会因不同的语言而改变)。

现在,我们可以在IndexPages上创建一个方法,该方法导航到CreateOrderPages。

public CreateOrderPage createOrder() {createOrderLink.click();return new CreateOrderPage(drv, siteBase);}

最后,我们可以在IndexPageIT中为此链接创建一个测试:

@Testpublic void testCreateOrder() {getDrv().get(getSiteBase().toString());new IndexPage(getDrv(), getSiteBase()).createOrder();assertTrue(CreateOrderPage.isAtCreateOrderPage(getDrv(), getSiteBase()));}

执行mvn verify,您应该找到新的测试通过。 至此,我们有两个测试无法在它们之间进行清理。 他们在两个测试中使用相同的WebDriver实例,最后一页仍将打开,并且设置的所有cookie都将保持不变。 为多个测试创建单个WebDriver实例的优缺点。 主要优点是减少了打开和关闭浏览器的时间,但缺点是每次测试,Cookie设置和弹出窗口打开后,浏览器实际上都会变脏。 我们可以使用AbstractIT中的适当setUp方法确保每次测试之前它都是干净的:

@Beforepublic void setUp() {getDrv().manage().deleteAllCookies();getDrv().get(siteBase.toString());}

有其他方法可以解决,我将让您自行研究在每次测试之前创建新的WebDriver实例的方法。

@FindBy批注在窗体上使用时特别有用。 向create-order.jsp添加新表单:

<form method="post" name="create-order">Item: <input name="item"/> <br/>Amount: <input name="amount"/><br/><input type="submit"/></form>

将这些WebElement添加到CreateOrderPage中,并添加一种提交表单的方法:

@FindBy(css = "form[name='create-order'] input[name='item']")private WebElement itemInput;@FindBy(css = "form[name='create-order'] input[name='amount']")private WebElement amountInput;@FindBy(css = "form[name='create-order'] input[type='submit']")private WebElement submit;public CreateOrderPage(WebDriver drv, URI siteBase) {if (!isAtCreateOrderPage(drv, siteBase)) { throw new IllegalStateException(); }PageFactory.initElements(drv, this);this.drv = drv;this.siteBase = siteBase;}public CreateOrderPage submit(String item, String amount) {itemInput.sendKeys(item);amountInput.sendKeys(amount);submit.click();return new CreateOrderPage(drv, siteBase);}

最后,我们可以为此创建一个测试:

package tutorial;import static org.junit.Assert.*;import org.junit.Test;public class CreateOrderPageIT extends AbstractIT {@Testpublic void testSubmit() {new IndexPage(getDrv(), getSiteBase()).createOrder().submit("foo", "1.0");}
}

结论

您可能要注意的一件事是,submit方法不需要将金额作为您期望的数字。 您可以创建一个测试以查看提交的是字符串而不是数字。 集成测试的编写可能很耗时,并且由于诸如元素ID或输入名称之类的事物的更改而容易损坏。 结果,创建它们所获得的最大好处是,最初仅在您站点内的业务关键路径上创建它们,例如,产品订购,客户注册流程和付款。

在本教程的下一部分中,我们将研究使用一些数据支持测试以及由此带来的挑战。

参考:我们的JCG合作伙伴 Alex Collins在Alex Collins的博客上提供的教程 教程:与硒的集成测试–第1部分 , 教程:与硒的集成测试–第2部分 。


翻译自: https://www.javacodegeeks.com/2012/04/integration-testing-with-selenium.html

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

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

相关文章

linux每天一小步---sed命令详解

1 命令功能 sed是一个相当强大的文件处理编辑工具&#xff0c;sed用来替换&#xff0c;删除&#xff0c;更新文件中的内容。sed以文本行为单位进行处理&#xff0c;一次处理一行内容。首先sed吧当前处理的行存储在临时的缓冲区中&#xff08;称为模式空间pattern space&#xf…

mysql trace工具_100% 展示 MySQL 语句执行的神器-Optimizer Trace

在上一篇文章《用Explain 命令分析 MySQL 的 SQL 执行》中&#xff0c;我们讲解了 Explain 命令的详细使用。但是它只能展示 SQL 语句的执行计划&#xff0c;无法展示为什么一些其他的执行计划未被选择&#xff0c;比如说明明有索引&#xff0c;但是为什么查询时未使用索引等。…

MOXy作为您的JAX-RS JSON提供程序–服务器端

在以前的系列文章中&#xff0c;我介绍了如何利用EclipseLink JAXB&#xff08;MOXy&#xff09;创建RESTful数据访问服务。 在本文中&#xff0c;我将介绍在服务器端利用MOXy的新JSON绑定添加对基于JAXB映射的JSON消息的支持有多么容易。 MOXy作为您的JAX-RS JSON提供程序–服…

006_过滤器

过滤器 过滤器&#xff08;Filter&#xff09;把附加逻辑注入到MVC框的请求处理&#xff0c;实现了交叉关注。所谓交叉关注&#xff08;Cross-Cutting Concerns&#xff09;&#xff0c;是指可以用于整个应用程序&#xff0c;而又不适合放置在某个局部位置的功能&#xff0c;否…

Android_项目文件结构目录分析

android项目文件结构目录分析 在此我们新建了一个helloworld的项目&#xff0c;先看一些目录结构&#xff1a; 这么多的文件夹和文件中&#xff0c;我们重点关注是res目录、src目录、AndroidManifest.xml文件&#xff1a; 一、res目录主要是用来存放android项目的各种资源文件&…

实体 联系 模型mysql_数据库系统概念读书笔记――实体-联系模型_MySQL

bitsCN.com数据库系统概念读书笔记——实体-联系模型前言为了重新回顾我写的消息系统架构&#xff0c;我需要重新读一下数据库系统概念的前三章&#xff0c;这里简单的做一个笔记&#xff0c;方便自己回顾基本概念实体-联系(E-R)数据模型基于对现实世界的这样一种认识&#xff…

使用Twitter Bootstrap,WebSocket,Akka和OpenLayers玩(2.0)

原始帖子可以在ekito网站上找到。 对于我们的一位客户&#xff0c;我们需要显示一张具有实时更新的车辆位置的地图。 因此&#xff0c;我开始使用Play制作原型&#xff01; 框架及其最新发布的版本2.0&#xff0c;使用Java API。 我从Play的网络聊天室开始&#xff01; 2.0个样…

同步时间

同步时间 [rootlocalhost 03]# ntpdate 0.centos.pool.ntp.org 转载于:https://www.cnblogs.com/cglWorkBook/p/5556920.html

mysql 5.6.23免安装_mysql5.6.23免安装配置

1.官网下载&#xff0c;并解压2.环境变量&#xff0c;path下&#xff0c;追加mysql的bin路径D:\Program Files\mysql\bin;3.mysql目录下的my-default.ini重命名为my.ini&#xff0c;并添加下面的代码basedirD:/Program Files/mysql #mysql路径datadirD:/Program Files/mysql/d…

在Intellij IDEA中运行Vaadin应用

在本文中&#xff0c;我将向您展示如何使用Intellij IDEA运行vaadin应用程序。 Vaadin提供了一些用于Eclipse和Netbeans的插件。 但是对于Intellij IDEA来说&#xff0c;还没有插件。 但是部署vaadin应用程序比其他两个IDE容易。 这是您要遵循的步骤。 1.首先创建一个新项目&am…

mysql主从数据库

Mysql主从配置&#xff0c;实现读写分离 大型网站为了软解大量的并发访问&#xff0c;除了在网站实现分布式负载均衡&#xff0c;远远不够。到了数据业务层、数据访问层&#xff0c;如果还是传统的数据结构&#xff0c;或者只是单单靠一台服务器扛&#xff0c;如此多的数据库连…

安装openstack时遇到的错误

学习opensatck的第一步是安装DevStack来进行本机操作 1. 下面命令没有权限&#xff0c;解决办法&#xff1a;切换到root用户下执行sudo -s echo "stack ALL(ALL) NOPASSWD: ALL" >> /etc/sudoers2. 执行下面命令提示没有git&#xff0c;解决办法&#xff1a;su…

Java EE 6示例– Galleria –第3部分

关于Galleria示例的先前文章&#xff08; 第1 部分 | 第2部分 | 第3部分 | 第4部分 &#xff09;指导您完成基础知识以及对GlassFish和WebLogic的初始部署。 从今天开始&#xff0c;我尝试在其中添加一些企业级功能&#xff0c;因为我发现他们在自己的项目中提出了很多要求。 我…

在 Windows 上测试 Redis Cluster的集群填坑笔记

redis 集群实现的原理请参考http://www.tuicool.com/articles/VvIZje集群环境至少需要3个节点。推荐使用6个节点配置&#xff0c;即3个主节点&#xff0c;3个从节点。新建6个文件夹 分别是 7000/7001/7002/7003/7004/7005将redis.windows.conf 复制一份然后修改配置文件中的下面…

不成为编程天才的5种贡献方式

安迪莱斯特&#xff08;Andy Lester&#xff09;早在三月发布了原始指南&#xff0c;其中介绍了14种不成为编程天才或摇滚明星的贡献开源的方法 &#xff0c;我真的很喜欢这个想法。 这就是为什么我决定稍微采纳一下这篇文章&#xff0c;并告诉您如何以及可以做什么来支持自己喜…

mysql数据库设计与应用答案智慧树_智慧树_MySQL数据库设计与应用_完整免费答案...

单位工程施工组织设计的技术经济指标体系包括有()。A&#xff0e;工期指标B&#xff0e;劳动指标C&#xff0e;台班利用率D&#xff0e;成本降低大跨径桥梁采用()将会取得良好的技术经济效益。A&#xff0e;横移法施工B&#xff0e;顶推法施工C&#xff0e;转体法施工D&#xf…

拓扑排序最长链-P3119 [USACO15JAN]草鉴定Grass Cownoisseur

https://www.luogu.org/problem/show?pid3119 本来我是来练习tarjan的&#xff0c;结果tarjan部分直接copy了&#xff0c;反而拓扑排序部分想了好久&#xff1b; 这道题SZB大神两次就AC&#xff1b; 但我等到AC&#xff0c;写好题解就只能洗洗睡了&#xff1b; 唉~ 差距怎…

谈谈父类和子类的隔离性

以前写代码知道要给类外设置访问接口, 例如下例: 1 class Money2 {3 public:4 Money(int money) : m_curValue(money){}5 6 void store(int money) { m_curValue money;}7 void spent(int money){ m_curValue - money;}8 private:9 int m_curValue…

用于数据库测试的DBUnit,Spring和注释

如果您曾经尝试用Java编写数据库测试&#xff0c;则可能会碰到DBUnit 。 DBUnit允许您设置和拆除数据库&#xff0c;以便它包含可针对其编写测试的一致行。 通常&#xff0c;您可以通过编写一个简单的XML文档来指定要DBUnit插入的行&#xff0c;例如&#xff1a; <?xml ve…