如何使用go-sqlmock模拟Ping命令?兼容*sql.DB的方案
sql.DB.Ping() with go-sqlmock Absolutely, you can simulate the Ping() method with go-sqlmock—even though there's no built-in ExpectPing() helper, the library gives you the flexibility to override the underlying driver's behavior to make this work. Here's how to do it properly:
Step 1: Override the Mock Driver's Ping Method
The sql.DB.Ping() call ultimately delegates to the underlying driver's Ping() method. go-sqlmock's MockDriver exposes this method directly, so you can replace it with your custom mock logic.
Here's a complete test example matching what you wanted:
import ( "context" "errors" "testing" "github.com/DATA-DOG/go-sqlmock" ) func TestDBPingMock(t *testing.T) { // Create the mock DB and mock instance db, mock, err := sqlmock.New() if err != nil { t.Fatalf("failed to initialize sqlmock: %v", err) } defer db.Close() // Mock the Ping behavior to return your desired error mock.Driver().Ping = func(ctx context.Context) error { return errors.New("mock error") } // Execute the Ping call err = db.Ping() if err == nil { t.Fatal("expected an error from Ping(), got nil instead") } // Verify all expectations (if you have other SQL expectations) if err := mock.ExpectationsWereMet(); err != nil { t.Fatalf("unfulfilled SQL expectations: %v", err) } }
Step 2: Inject the Mock DB into Your New Function
Good news—this mock *sql.DB is fully compatible with the standard library's type, so you can pass it directly to any function that accepts a *sql.DB parameter. For example:
// Your existing New function func New(db *sql.DB) *YourStruct { return &YourStruct{DB: db} } // In your test testStruct := New(db) // Works perfectly with the sqlmock DB
Advanced: Simulate Dynamic Ping Behavior
If you need to mock varying Ping results (e.g., success on first call, failure on the second), you can use a closure to track state:
pingAttempts := 0 mock.Driver().Ping = func(ctx context.Context) error { pingAttempts++ if pingAttempts == 1 { return nil // First Ping succeeds } return errors.New("mock failure on subsequent Pings") }
Do You Need a Different Library?
Nope—go-sqlmock is fully capable of handling this use case. The lack of an ExpectPing() helper is just a missing convenience method, not a limitation of the library's core functionality. If you did want to explore alternatives, libraries like github.com/golang/mock paired with custom driver mocks work, but they're more verbose than the approach above.
Sticking with go-sqlmock is the simplest and most consistent choice here, since you're already using it for other database mocks.
内容的提问来源于stack exchange,提问作者dsncode

