如何为 Saturn 应用构建集成测试
How to build integrations tests for a Saturn app
我正在尝试为我使用 Saturn framework.
构建的小型 API 构建一些集成测试
API 是用常用的 Saturn
计算表达式构建的,例如 application
、controller
、router
等
但是为了构建集成测试,我需要替换 application
计算表达式 (ce) 并手工制作一个 WebHostBuilder
。
我的 application
ce 看起来像这样:
module Server
let app =
application {
url ("http://0.0.0.0:" + port.ToString() + "/")
use_router apiRouter
memory_cache
service_config configureSerialization
use_gzip
use_config (fun _ ->
System.Environment.CurrentDirectory <- (System.Reflection.Assembly.GetExecutingAssembly()).Location
|> Path.GetDirectoryName
let configurationRoot =
ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appSettings.json")
.Build()
let appConfig = FsConfig.AppConfig(configurationRoot)
let dbPath =
match appConfig.Get<AppSettings>() with
| Ok settings when settings.DbConfig.Database.Contains(":memory:") -> settings.DbConfig.Database
| Ok settings -> Path.Combine(System.Environment.CurrentDirectory, settings.DbConfig.Database)
| Error _ -> failwithf "Invalid database path"
{ connectionString = dbPath |> sprintf "DataSource=%s;Version=3" })
}
有 router
和其中一个 controllers
...
let cartController =
controller {
create createCartAction
show getCartAction
delete deleteCartAction
subController "/items" cartItemsController
}
let apiRouter =
router {
not_found_handler (setStatusCode 404 >=> text "Not found")
pipe_through apiPipeline
forward "/cart" cartController
}
上面的代码在我的API项目中,下面集成测试的代码在第二个项目中。后者有前者的项目参考。
let configureApp (app : IApplicationBuilder) =
app.UseGiraffe(Server.apiRouter) \<-- The problem is here. Server.apiRouter is null!
let configureServices (services : IServiceCollection) =
services.AddGiraffe() |> ignore
let builder = WebHostBuilder()
.UseContentRoot(contentRoot)
.Configure(Action<IApplicationBuilder> configureApp)
.ConfigureServices(configureServices)
let testServer = new TestServer(builder)
let client = testServer.CreateClient()
let! response = client.GetAsync "/"
test <@ HttpStatusCode.OK = response.StatusCode @>
当测试为 运行 时,它失败并出现以下异常:
System.InvalidOperationException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'A suitable constructor for type 'Giraffe.Middleware+GiraffeMiddleware' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.'
问题似乎出在行 app.UseGiraffe(Server.apiRouter)
上。 apiRouter
是在 API 项目的 Server
模块中定义的 - 但是当测试项目 Server.apiRouter
中的这段代码 运行 是 null
时。
但是,如果我将测试代码移动到与 API
相同的项目中 - 测试将完美运行。
为什么从测试项目中调用apiRouter
计算表达式会是null
?
原来这跟Saturn
一点关系都没有。这与 F#
启动 modules
的方式有关。 The answer can be found here
如所引用的 post 中的建议。我只是添加了一个 [<EntryPoint>]
函数,一切都按预期工作。
我正在尝试为我使用 Saturn framework.
构建的小型 API 构建一些集成测试 API 是用常用的 Saturn
计算表达式构建的,例如 application
、controller
、router
等
但是为了构建集成测试,我需要替换 application
计算表达式 (ce) 并手工制作一个 WebHostBuilder
。
我的 application
ce 看起来像这样:
module Server
let app =
application {
url ("http://0.0.0.0:" + port.ToString() + "/")
use_router apiRouter
memory_cache
service_config configureSerialization
use_gzip
use_config (fun _ ->
System.Environment.CurrentDirectory <- (System.Reflection.Assembly.GetExecutingAssembly()).Location
|> Path.GetDirectoryName
let configurationRoot =
ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appSettings.json")
.Build()
let appConfig = FsConfig.AppConfig(configurationRoot)
let dbPath =
match appConfig.Get<AppSettings>() with
| Ok settings when settings.DbConfig.Database.Contains(":memory:") -> settings.DbConfig.Database
| Ok settings -> Path.Combine(System.Environment.CurrentDirectory, settings.DbConfig.Database)
| Error _ -> failwithf "Invalid database path"
{ connectionString = dbPath |> sprintf "DataSource=%s;Version=3" })
}
有 router
和其中一个 controllers
...
let cartController =
controller {
create createCartAction
show getCartAction
delete deleteCartAction
subController "/items" cartItemsController
}
let apiRouter =
router {
not_found_handler (setStatusCode 404 >=> text "Not found")
pipe_through apiPipeline
forward "/cart" cartController
}
上面的代码在我的API项目中,下面集成测试的代码在第二个项目中。后者有前者的项目参考。
let configureApp (app : IApplicationBuilder) =
app.UseGiraffe(Server.apiRouter) \<-- The problem is here. Server.apiRouter is null!
let configureServices (services : IServiceCollection) =
services.AddGiraffe() |> ignore
let builder = WebHostBuilder()
.UseContentRoot(contentRoot)
.Configure(Action<IApplicationBuilder> configureApp)
.ConfigureServices(configureServices)
let testServer = new TestServer(builder)
let client = testServer.CreateClient()
let! response = client.GetAsync "/"
test <@ HttpStatusCode.OK = response.StatusCode @>
当测试为 运行 时,它失败并出现以下异常:
System.InvalidOperationException' occurred in System.Private.CoreLib.dll but was not handled in user code: 'A suitable constructor for type 'Giraffe.Middleware+GiraffeMiddleware' could not be located. Ensure the type is concrete and services are registered for all parameters of a public constructor.'
问题似乎出在行 app.UseGiraffe(Server.apiRouter)
上。 apiRouter
是在 API 项目的 Server
模块中定义的 - 但是当测试项目 Server.apiRouter
中的这段代码 运行 是 null
时。
但是,如果我将测试代码移动到与 API
相同的项目中 - 测试将完美运行。
为什么从测试项目中调用apiRouter
计算表达式会是null
?
原来这跟Saturn
一点关系都没有。这与 F#
启动 modules
的方式有关。 The answer can be found here
如所引用的 post 中的建议。我只是添加了一个 [<EntryPoint>]
函数,一切都按预期工作。