groovy 当使用从CSV提取的数据时,Jmeter HTTP请求给出400,但是当手动传递请求主体上的数据时,Jmeter HTTP请求工作正常

vsikbqxv  于 2023-01-29  发布在  其他
关注(0)|答案(1)|浏览(170)

我在Jmeter中有两个HTTP GET请求。第一个请求调用服务器并获取包含一些用户数据的CSV。我使用JSR223后处理器,将数据Map到JSON,并将值分配给三个变量以传递到第二个请求。执行此操作的脚本如下所示。

import org.apache.commons.io.IOUtils
import java.nio.charset.StandardCharsets
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
import groovy.json.JsonOutput

def response = prev.getResponseDataAsString()
def lines = response.split('\n')

def userData = []
for (int i = 1; i < lines.length; i++) {
    def line = lines[i]
    def tokens = line.split(',')
    userData << [login_type: tokens[0], username: tokens[1], password: tokens[2]]
}

def jsonString = JsonOutput.toJson(userData)
def jsonSlurper = new JsonSlurper()
def jsonMap = jsonSlurper.parseText(jsonString)

for (int i = 1; i <= Math.min(jsonMap.size(), Integer.parseInt("${__P(threads)}")); i++) {
    if(i < jsonMap.size()){
        vars.put("login_type" , jsonMap[Integer.parseInt("${__threadNum}")-1].login_type)
        vars.put("username" , jsonMap[Integer.parseInt("${__threadNum}")-1].username)
        vars.put("password" , jsonMap[Integer.parseInt("${__threadNum}")-1].password)
    }
}

我在下一个请求主体中传递这三个变量,作为{"login_type":"${login_type}","username":"${username}","password":"${password}"}
当运行脚本时,我得到的第二个请求的响应为400,即使我可以看到数据正在通过。

POST data:
{"login_type":"data","username":"data","password":"data"}

我尝试了第二个请求,手动给出登录数据而不是变量,它工作正常。{"login_type":"EMAIL","username":"username","password":"pass"}
两次尝试的唯一区别是在请求头中,手动发送数据时显示Content-Length: 83,从groovy脚本传递数据时显示Content-Length: 84。尽管我不认为这是导致问题的原因。有人能解释一下为什么会发生这种情况以及如何修复吗?
我查看了请求,发现来自Groovy脚本的POST请求正文在末尾有一个换行符。

{"login_type":"login_type","username":"username","password":"password
"}

因此导致请求抛出一个400。我怎么能在一行中发送正文数据呢?

wkyowqbh

wkyowqbh1#

也许有一些看不见的字符,比如空格或换行符,这是测试系统所期望的,但在Groovy中填充变量时没有发送。
使用WiresharkFiddler之类的嗅探器工具逐字节比较这两个请求,并修改JMeter配置或Groovy代码以100%匹配"手动"请求。
另外,关于脚本中JMeter Functions的用法,请参见JSR223采样器文档:
JSR223测试元素有一个功能(编译)可以显著提高性能。要从该功能中获益:

  • 使用脚本文件而不是内联它们。如果ScriptEngine上有此功能,这将使JMeter编译它们并缓存它们。
  • 或者使用脚本文本并选中"如果可用,则缓存已编译脚本"属性。

使用此功能时,请确保脚本代码不直接在脚本代码中使用JMeter变量或JMeter函数调用,因为缓存只会缓存第一个替换。请改用脚本参数。
因此替换:

  • ${__P(threads)}props.get('threads')
  • ${__threadNum}ctx.getThreadNum()

请参见Top 8 JMeter Java Classes You Should Be Using with Groovy,了解更多关于propsctx的信息。

相关问题