You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go使用go-sqlmock测试MySQL插入逻辑报错,求解决方法

Fixing go-sqlmock Error: Prepare Statement Not Expected

Got it, let's break down why your test is failing and how to fix it quickly.

The Root Cause

Your PostDao function first calls db.Prepare() to create a prepared statement, then executes it with ins.Exec(). But in your test, you only defined an ExpectExec() expectation—sqlmock is waiting for an Exec call directly, but instead gets a Prepare call that it didn't expect. That's exactly what the error message is telling you.

Solution 1: Update the Test to Match Prepare + Exec Flow

If you want to keep using Prepare in your DAO code, you need to adjust the test to first expect the Prepare call, then chain the Exec expectation onto it. Here's how to modify your test code:

func TestPostArticleDao(t *testing.T) {
    db, mock, err := sqlmock.New()
    if err != nil {
        t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
    }
    defer db.Close()

    // First expect the Prepare call, then chain the Exec expectation
    mock.ExpectPrepare("^INSERT INTO articles*").
        ExpectExec().
        WithArgs("bea1b24d-0627-4ea0-aa2b-8af4c6c2a41c", "test", "test").
        WillReturnResult(sqlmock.NewResult(1, 1))

    article := util.Article{ ID: 1, TITLE: "test", CONTENT: "test" }
    PostDao(db, article, "bea1b24d-0627-4ea0-aa2b-8af4c6c2a41c")

    if err := mock.ExpectationsWereMet(); err != nil {
        t.Errorf("there were unfulfilled expections: %s", err)
    }
}

This way, sqlmock will first match the Prepare call from your DAO, then expect the subsequent Exec on the prepared statement.

Solution 2: Simplify DAO Code to Use db.Exec Directly

For single-execution statements like this insert, you don't need to use Prepare at all—db.Exec() is more concise and efficient. Modify your PostDao function like this:

func PostDao(db *sql.DB, article util.Article, uu string) {
    _, err := db.Exec("INSERT INTO articles(uuid, title,content) VALUES(?,?,?)", uu, article.TITLE, article.CONTENT)
    if err != nil { 
        log.Fatal(err) 
    }
}

With this change, your original test code will work as-is, since now the DAO calls db.Exec() directly, which matches your existing ExpectExec() expectation.

Quick Note on SQL Matching

Your regex ^INSERT INTO articles* works for this test, but if you want to make it more precise (to avoid accidental matches with other queries), you can use a more specific pattern like:

^INSERT INTO articles\(uuid, title,content\) VALUES\(\?,\?,\?\)$

内容的提问来源于stack exchange,提问作者jpskgc.v5

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:08:03