我尝试构建多种加特林模拟,以便在构建不同场景时重用低级调用(即HTTP调用)。因此,我具有以下结构(为了解释当前状态,使用了echo函数):
// File UserAction.scala contains all low-level actions like load a specific page, login, logout etc. All functions return HttpRequestBuilder so that each simulation can perform its own set of checks on the responses.
object UserAction {
...
def echo(): HttpRequestBuilder = {
http("Postman Echo Service Call")
.get("https://postman-echo.com/get")
.headers(headers("headers_0"))
}
...
}
// File TestSimulation.scala
class TestSimulation extends ParameterizedSimulation {
private val accountFeeder = csv("data/accounts.csv")
private val testScenario = scenario("Test Simulation")
.feed(accountFeeder)
.exec { session =>
session.set("attributes", session.attributes.filterKeys(key => key.startsWith("some_prefix_")))
}
.doIfOrElse(session => session("schema_attributes").as[Map[String, String]].isEmpty) {
exec(
echo()
.check(bodyString.saveAs("responseBody"))
)
} {
exec(
echo()
.formParamMap("${schema_attributes}")
.check(bodyString.saveAs("responseBody"))
)
}
.exec { session => println(session("responseBody").as[String]); session }
...
}
在上面提供的测试模拟中,我们从文件中获取数据,然后选择属性的子集,将其作为Map存储到Session中。如果在文件中找到此类属性,则在提交回显请求时,我们会将它们作为表单参数添加。否则我们不会。在这两种情况下,我们都存储响应主体并也将其打印出来。效果很好。
当我尝试将Map作为参数传递给echo()时,问题就开始了。假设我具有以下回显实现:
def echo(extraParameters: Map[String, Any]): HttpRequestBuilder = {
val request = http("Postman Echo Service Call")
.get("https://postman-echo.com/get")
.headers(headers("headers_0"))
if (extraParameters.nonEmpty) {
request.formParamMap(extraParameters)
}
request
}
,并且模拟执行以下操作:
.exec { session =>
session.set("schema_attributes", session.attributes.filterKeys(key => key.startsWith("some_prefix_")))
}
.exec { session =>
echo(session.attributes.filterKeys(key => key.startsWith("some_prefix_")))
.check(bodyString.saveAs("responseBody"))
session
}
.exec { session => println(session("responseBody").as[String]); session }
请求不会触发,并且我收到有关bodyString丢失的以下错误消息
[ERROR] i.g.c.a.b.SessionHookBuilder$$anon$1 - 'hook-1' crashed with 'j.u.NoSuchElementException: No attribute named 'responseBody' is defined', forwarding to the next one
我尝试的另一种方法是使echo接受Expression[Map[String, Any]]
并使用普通的exec块(即,不是带有注入会话的那个)。在那种情况下,我无法从会话中获得实际的地图!
似乎bodyString仅在使用exec()而不是exec {session => ...;时才可用。会话}表单。我对Scala的了解很少,这使我更加困惑。
我觉得我缺少一些非常基本的东西。任何帮助将不胜感激。
更新#1
根据到目前为止所收到的评论,据我所知,使用exec(sessionFunction: Expression[Session])
函数可在运行时创建ActionBuilders,以便不使用它们(它们只是创建并丢弃)。
为了将所有检查保留在方案中,同时将HTTP请求的定义保留在其他函数上,我尝试了以下替代方法:
def echo(): HttpRequestBuilder = {
http("Postman Echo Service Call")
.get("https://postman-echo.com/get")
.headers(headers("headers_0"))
.formParamMap("${schema_attributes}")
}
// Used as
.feed(myFeeder)
.exec { session => session.set("schemaAttributes", session.attributes.filterKeys(key => key.startsWith("some_prefix_")))
}
.exec(
echo()
.check(bodyString.saveAs("responseBody"))
)
这样,我遇到的问题是,如果映射为空(即文件中不存在信息),formParamMap
将无法正常工作。如果地图实际包含数据,是否可以选择添加formParamMap?
通常,是否存在将参数传递给从场景中返回HttpRequestBuilder
的函数的首选模式/方法?例如,如果我有另一个将Int作为参数并使用要发送的请求中的数字创建HTTP请求的函数,我该怎么做呢?
答案 0 :(得分:1)
在您的示例中,echo
返回HttpRequestBuilder。加特林的工作方式是,构建器应该全部在启动时构建,然后用于发出请求,因此,当您将其包含在会话函数中时,构建器会在执行过程中创建,但实际上并不会执行,返回未更改的会话。
要执行此操作,您将必须将echo
从会话功能中移出。正如您已经意识到的那样,您可能必须更改方法签名才能接受某种表达式