繁体   English   中英

如何编写数据库单元测试?

[英]How do I write a database unit test?

我正在使用MongoDB,Java,JDO和Maven。

我运行了一个简单的主应用程序,该应用程序存储了一些垃圾数据并从mongodb中检索了数据,看起来还不错,但是我想开始编写适当的单元测试。 模拟实际的数据库交互对我似乎没有太大帮助,因此从技术上讲,我想编写功能测试来检查与数据库的完整交互。

我的单元测试设置如下:

static final Logger LOG = LoggerFactory.getLogger(DaoTest.class);
static final int PORT = 100001;
static Process mongod;
static PersistenceManagerFactory pmf;

// Class under test.
Dao dao;

@BeforeClass
public static void beforeAll() throws Exception {
  File mongoDir = new File(
      System.getProperty("java.io.tmpdir"),
      "mongodb-" + System.currentTimeMillis());
  mongoDir.deleteOnExit();
  mongod = Runtime.getRuntime().exec(String.format(
      "/bin/sh -c mongod --dbpath=%s --port=%d",
      mongoDir.getAbsolutePath(),
      PORT));
  LOG.info("Mongodb using {} on port {}.", mongoDir.getAbsolutePath(), PORT);
  Thread.sleep(1000);
  pmf = JDOHelper.getPersistenceManagerFactory("mongodbtest");
  LOG.info("DB connection URL: {}.", pmf.getConnectionURL());
}

@AfterClass
public static void afterAll() throws Exception {
  mongod.destroy();
}

@Before
public void setUp() throws Exception {
  dao = new Dao(pmf);
}

src / test / resources / META-INF / persistence.xml如下所示:

<?xml version="1.0" encoding="UTF-8" ?>
<persistence ...>
  <persistence-unit name="mongodbtest">
    <properties>
      <property name="javax.jdo.PersistenceManagerFactoryClass"
          value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory" />
      <property name="javax.jdo.option.ConnectionURL" value="mongodb://localhost:100001/contacts"/>
      <property name="javax.jdo.option.RetainValues" value="true"/>
      <property name="datanucleus.autoCreateSchema" value="true" />
      <property name="datanucleus.validateTables" value="false" />
      <property name="datanucleus.validateConstraints" value="false" />
      <property name="datanucleus.storeManagerType" value="mongodb" />
    </properties>
  </persistence-unit>
</persistence>

最后,我使用mvn clean test执行单元测试,只有在添加尝试保存数据的实际测试之前,该单元测试才能起作用。 我收到以下错误:

Mongodb using /var/folders/00/0l550000h01000cxqpysvccm002cmm/T/mongodb-1373820849219 on port 100001.
DB connection URL: mongodb://localhost:100001/contacts.
Jul 14, 2013 12:54:10 PM com.mongodb.DBTCPConnector initDirectConnection
WARNING: Exception executing isMaster command on localhost/127.0.0.1:27017
java.io.IOException: couldn't connect to [localhost/127.0.0.1:27017] bc:java.net.ConnectException: Connection refused
    at com.mongodb.DBPort._open(DBPort.java:214)
    at com.mongodb.DBPort.go(DBPort.java:107)

...

Jul 14, 2013 12:54:10 PM com.mongodb.DBTCPConnector initDirectConnection
WARNING: Exception executing isMaster command on localhost/127.0.0.1:27017
java.io.IOException: couldn't connect to [localhost/127.0.0.1:27017] bc:java.net.ConnectException: Connection refused
    at com.mongodb.DBPort._open(DBPort.java:214)
    at com.mongodb.DBPort.go(DBPort.java:107)

...

ul 14, 2013 12:54:10 PM com.mongodb.DBPortPool gotError
WARNING: emptying DBPortPool to localhost/127.0.0.1:27017 b/c of error
java.io.IOException: couldn't connect to [localhost/127.0.0.1:27017] bc:java.net.ConnectException: Connection refused
    at com.mongodb.DBPort._open(DBPort.java:214)
    at com.mongodb.DBPort.go(DBPort.java:107)

...

Jul 14, 2013 12:54:10 PM org.datanucleus.store.valuegenerator.AbstractGenerator obtainGenerationBlock
INFO: Error encountered allocating block of IDs : can't call something : localhost/127.0.0.1:27017//localhost:100001/contacts

127.0.0.1:27017是mongodb的默认设置,但我不知道为什么要使用它。 我可以看到它正在从我的persistence.xml文件中提取配置,所以我很困惑。 mongo 文档说连接字符串URL格式为:

mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]

到目前为止,我只是通过maven来运行它,因为到目前为止,我还剩下一个问题,那就是如何在Eclipse中运行这些单元测试。 我认为必须在字节码增强过程中进行这些测试才能在Eclipse中运行,并且我不知道该如何设置。

我猜我不是第一个想要做这样的事情的人。 是否有使用Java编写功能数据库测试的标准实践? 我要解决所有问题吗?

回答我自己的问题。 存在三个问题:

1)连接字符串应为:

mongo:/127.0.0.1/contacts

(注意少一个“ /”)

2)我需要添加mongoDir.mkdir();

3)启动服务器的命令应该是

String command = String.format(
    "/bin/sh -c mongod --dbpath=%s --port=%d", 
    mongoDir.getAbsolutePath(), 
    PORT);
Runtime.getRuntime().exec(new String[] { "/bin/sh", "-c", command });

实际上,我最终为此创建了一个JUnit4 Runner,因此我可以在所有测试中拥有相同的数据库,并让各个测试来管理该数据库的状态。

如果您想运行一个数据库实例进行测试(仅在您的Maven构建运行时运行),那么您可能会对我基于flappoodle Embedded Mongo API编写的Maven插件感兴趣:

embedmongo-maven-plugin

好处之一是该插件会自动下载Mongo发行版,因此人们无需安装Mongo即可运行您的Maven构建。 迁移到其他Mongo版本也很容易。 您只需更改插件配置即可。

考虑一下您的目标, I ran a simple main application that stores some junk data and retrieves it from mongodb and it looks ok, but I want to start writing proper unit tests.

如果您在团队中工作,您会发现当前的源代码有问题。 如果您的另一个团队成员如何使用登台db? 重现与db有关的错误,将使您的数据无用,不一致且痛苦。

我认为@joelittlejohn的解决方案更好。 在您的项目上使用Embedded-mongo。 目前,我在项目中使用https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo 您可以毫不犹豫地对mongo做任何事情。 因为它只是在运行test时发生

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM