2017-07-11 23 views
0

我有一个使用MySQL的gRPC服务,需要在每个测试用例后清除记录。我尝试用事务来包装每个测试用例。如果我的rpc代码中没有事务,但是如果没有事务,它就会起作用。而且还会有类似的错误:如何测试使用数据库(mysql)的Go代码?

can't start transaction 
... 
sql: Transaction has already been committed or rolled back 

然后我尝试使用截断清除记录,但一些测试用例失败随机。

我的代码是这样(我用GORM):

func foo(db *gorm.DB) { 
    tx := db.Begin() 
    // query and insert 
    tx.Commit() 
} 
// Use transaction to do database cleanup 
func TestFooVersion1() { 
    testDB := initDB() 
    tx = testDB.Begin() // setup 
    foo(testDB) 
    tx.Rollback() // teardown 
} 
// Use truncate to do database cleanup 
func TestFooVersion2() { 
    testDB := initDB() 
    foo(testDB) 
    truncateTables(testDB) // teardown 
} 
func truncateTables(db *gorm.DB) { 
    // exec "TRUNCATE TABLE table;" for every table 
} 

什么是测试使用DB(MySQL的)代码有道? (我不喜欢像go-sqlmock模拟)

回答

0

很难说没有看到代码,但基于错误,它听起来像你在多个测试之间共享连接,并且每个人都试图启动一个交易。确保每个测试都打开自己的连接,启动自己的事务,并在完成时提交或回滚并关闭连接。

+0

我添加了一些示例代码。问题是如果我在测试代码中使用事务(如'foo'函数),事务不起作用。 –

0

也许你可以使用docker进行集成测试。直接测试生成的具有活动mysql的容器。

您可以使用testify的测试套件。 每次测试时,运行docker容器,并使用live mysql进行测试。

+0

我有一个用于测试的mysql。但它不起作用。顺便说一句,我添加了一些示例代码来解释我的问题。 –

+0

我明白了。您的解决方案是为每个测试用例启动一个新的Docker容器。对? –

+0

是的......它会直接测试一个活的mysql –