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

如何在Yesod项目中结合Sqlite使用Hspec/Yesod.Test并解决类型匹配错误

问题原因

你遇到的类型报错核心来自两个不匹配:

  1. yesodSpecWithSiteGeneratorAndArgument 要求传入的站点生成器类型为 a -> IO App,即需要接收一个自定义参数,且返回包在IO中的App实例。你当前的代码既没有处理传入参数,最后也直接返回了App值而非IO包装的App。
  2. 绝大多数测试场景不需要传递额外自定义参数,直接用更简单的yesodSpecWithSiteGenerator即可,它只要求生成器返回IO App。

修改方案

无额外参数的常用版本(推荐)

shortblitoWebServerSpec :: Spec -> Spec
shortblitoWebServerSpec =
  yesodSpecWithSiteGenerator $
    withSqlitePool ":memory:" 1 $ \pool -> do
      let app = App
            { appLogLevel = LevelWarn
            , appStatic = shortblitoWebServerStatic
            , appConnectionPool = pool
            , appGoogleAnalyticsTracking = Nothing
            , appGoogleSearchConsoleVerification = Nothing
            }
      flip runSqlPool pool $ runMigration migrateTables
      pure app -- 把App实例包装为IO App,符合类型要求

需要传递自定义测试参数的版本

如果你确实需要给测试用例传递自定义配置,再用带参数的版本:

shortblitoWebServerSpec :: SpecWith App -> SpecWith a
shortblitoWebServerSpec =
  yesodSpecWithSiteGeneratorAndArgument $ \customArg -> -- 接收传入的自定义参数,可用于调整App配置
    withSqlitePool ":memory:" 1 $ \pool -> do
      let app = App
            { appLogLevel = LevelWarn
            , appStatic = shortblitoWebServerStatic
            , appConnectionPool = pool
            , appGoogleAnalyticsTracking = Nothing
            , appGoogleSearchConsoleVerification = Nothing
            }
      flip runSqlPool pool $ runMigration migrateTables
      -- 你可以在这里根据customArg修改App配置,或者插入测试数据
      pure app

注意事项

  • 内存SQLite数据库仅对同一个连接可见,所以测试用的连接池大小保持为1即可,避免出现表找不到的问题
  • 每次测试用例执行都会重新创建内存数据库,不同用例之间数据不会互相干扰
  • 如果需要提前插入测试数据,直接在runMigration语句后追加对应的SQL操作即可

内容的提问来源于stack exchange,提问作者The Oddler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 16:06:04