Buffalo框架的测试入口是actions/actions_test.go,它通过App()创建内存数据库和mock transport的*buffalo.App实例,所有测试须在actions/目录下运行并确保buffalo test正确加载test环境配置。

Buffalo 框架的测试入口在哪
Buffalo 项目默认生成的 actions/app.go 里没有测试入口,真正的测试起点是 actions/actions_test.go —— 它会调用 App() 创建一个测试用的 *buffalo.App 实例。这个实例和生产环境的 App 结构一致,但底层使用的是内存数据库(如 sqlite://:memory:)和 mock HTTP transport,不依赖真实服务。
关键点:所有测试必须在 actions/ 目录下运行,且需确保 buffalo test 命令能正确加载 actions.TestDB 配置(默认由 database.yml 的 test 环境决定)。
- 如果手动运行
go test,要先执行buffalo task db:create和buffalo task db:migrate(仅对 test DB) - 别直接在
models/下写测试——Buffalo 的模型层通常不带框架逻辑,用标准go test即可,无需App() -
buffalo test默认只跑actions/和models/下的*_test.go,不会自动包含grifts/或mailers/
如何测试一个 Buffalo handler(比如 GET /users)
核心是用 app.ServeHTTP() 模拟请求,并检查响应状态、JSON 内容或重定向目标。Buffalo 的 handler 是 buffalo.Handler 类型,不能直接传给 http.HandlerFunc。
示例:假设你有一个 UsersIndex handler 绑定到 GET /users:
Buffalo框架 1.0.1 版本源码包下载,适合需要错误处理改进、依赖更新、render.Download 注释和 request logger 调整的 v1 项目。
func TestUsersIndex(t *testing.T) {
app := App()
req := httptest.NewRequest("GET", "/users", nil)
res := httptest.NewRecorder()
app.ServeHTTP(res, req)
assert.Equal(t, http.StatusOK, res.Code)
assert.Contains(t, res.Body.String(), `"data":`)
}
- 务必用
app.ServeHTTP(),不是http.DefaultServeMux或自建http.Server - 如果 handler 依赖 session 或 auth,需提前设置:
req = buffalo.PopulateRequest(req, "session_key", "value") - JSON 响应建议用
json.Unmarshal解析后断言字段,而不是字符串匹配——否则容易因空格、换行失败
为什么测试时数据库迁移没生效
常见现象是 assert.NoError(t, models.DB.Create(...)) 报 no such table,本质是测试用的 models.DB 没有执行 migration。
Buffalo 的测试 DB 初始化逻辑藏在 models/models_test.go 的 TestTx 函数里,它默认只在 buffalo test 启动时自动调用一次。如果你在 actions/ 测试中直接 import models 并用 models.DB,它可能还是空连接。
- 解决办法:在每个测试函数开头加
models.LoadFixtures()(若用了 fixtures),或显式调用models.Migrate() - 更稳妥的方式是复用
actions.TestDB:它在actions/actions_test.go中已预配置好迁移后的 DB 连接 - 注意
models.DB和actions.TestDB是两个独立实例,事务不共享,别混用
测试 mailer 或 worker 时怎么避免发真实邮件
Buffalo 的 mailers 和 workers 默认走真实 SMTP 或后台队列,测试时必须拦截。框架本身不提供 mock 工具,得靠 Go 标准库或第三方包。
Mailer 测试推荐用 gomail 的 gomail.NewTester(),或者直接替换 mailers.App 的 Sender 字段为内存实现:
mailers.App.Sender = &mockSender{sent: []*gomail.Message{}}
// 然后调用 mailers.Send(...)
assert.Len(t, mockSender.sent, 1)
- Worker 测试同理:把
workers.App.Queue替换为内存队列(如github.com/vmihailenco/taskq/memoryq) - 千万别在测试里留
workers.App.Start()—— 它会阻塞主线程,导致测试超时 - Buffalo 7+ 的
workers默认用taskq,其memoryq不支持延迟任务,测试涉及Delay的逻辑要格外小心
:memory: SQLite 可能被不同 goroutine 拿到不同连接,导致数据“看不见”。真要并行,得用 PostgreSQL 的 template0 快速克隆 DB,或者老老实实用 -p 1 串行跑。

















