我正在使用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 docs表示连接字符串URL格式为:
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
到目前为止,我只是通过maven运行这个,因为这只是到目前为止,但我最终会遇到的另一个问题是如何在Eclipse中运行这些单元测试。我假设必须在Eclipse中运行这些测试的字节码增强过程,我不知道如何设置它。
我猜我不是第一个想做这样的事情的人。在Java中编写功能数据库测试是否有任何标准实践?我该怎么回事呢?
答案 0 :(得分:0)
回答我自己的问题。有三个问题:
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,所以我可以在所有测试中使用相同的数据库,然后通过单独的测试来管理该数据库的状态。
答案 1 :(得分:0)
如果你想运行一个数据库实例进行测试(只运行Maven构建运行的时间),那么你可能会对我基于flapdoodle嵌入式Mongo API编写的Maven插件感兴趣:
一个好处是该插件会自动下载Mongo发行版,因此人们无需在运行Maven版本之前安装Mongo。移动到不同的Mongo版本也很容易;你只需更改插件配置。
答案 2 :(得分:0)
思考您的目标
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做任何事情。 因为它在运行测试时会发生。