Groovy脚本获取MongoDB随机_id用于接口测试的报错求助
解决nGrinder Groovy脚本MongoDB依赖及编译错误问题
问题背景
我使用Groovy编写了基于nGrinder的接口测试脚本,userId已实现随机生成用于测试。现需将请求参数last_post_id(对应MongoDB的_id)也改为随机取值,实现思路是:1. 从MongoDB中获取所有_id并存入数组;2. 从数组中随机选取一个值。编写的脚本及运行时的编译错误如下:
原测试脚本
import static net.grinder.script.Grinder.grinder import static org.junit.Assert.* import static org.hamcrest.Matchers.* import net.grinder.script.GTest import net.grinder.script.Grinder import net.grinder.scriptengine.groovy.junit.GrinderRunner import net.grinder.scriptengine.groovy.junit.annotation.BeforeProcess import net.grinder.scriptengine.groovy.junit.annotation.BeforeThread // import static net.grinder.util.GrinderUtils.* // You can use this if you're using nGrinder after 3.2.3 import org.junit.Before import org.junit.BeforeClass import org.junit.Test import org.junit.runner.RunWith import org.ngrinder.http.HTTPRequest import org.ngrinder.http.HTTPRequestControl import org.ngrinder.http.HTTPResponse import org.ngrinder.http.cookie.Cookie import org.ngrinder.http.cookie.CookieManager @Grapes([ @Grab(group='org.mongodb', module='mongo-java-driver', version='3.12.12') ]) import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import org.bson.Document; /** * A simple example using the HTTP plugin that shows the retrieval of a single page via HTTP. * * This script is automatically generated by ngrinder. * * @author admin */ @RunWith(GrinderRunner) class TestRunner { public static GTest test public static HTTPRequest request public static Map<String, String> headers = [:] public static Map<String, Object> params = [:] public static List<Cookie> cookies = [] public static List<String> last_post_ids = [] public static final String db_name = "instaclone_post" public static final String collection_name = "post" @BeforeProcess public static void beforeProcess() { HTTPRequestControl.setConnectionTimeout(300000) test = new GTest(1, "127.0.0.1") request = new HTTPRequest() grinder.logger.info("before process.") } @BeforeThread public void beforeThread() { test.record(this, "test") grinder.statistics.delayReports = true grinder.logger.info("before thread.") } @Before public void before() { request.setHeaders(headers) CookieManager.addCookies(cookies) grinder.logger.info("before. init headers and cookies") def mongoClient = MongoClients.create("mongodb://localhost:27017") grinder.logger.info("before. create MongoClients") def collection = mongoClient.getDatabase(db_name).getCollection(collection_name) def documents = collection.find(new Document(), new Document("_id", 1)).into([]) for (document in documents) { println(document.get("_id")) last_post_ids.add(document.get("_id")) } } @Test public void test() { int userId = Math.abs(new Random().nextInt() % 10) + 1 Random rand = new Random(); HTTPResponse response = request.GET("http://127.0.0.1:8030/feed-server/feed/" + {userId} + "?last_post_id=" + last_post_ids.nextInt(5), params) if (response.statusCode == 301 || response.statusCode == 302) { grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", response.statusCode) } else { assertThat(response.statusCode, is(200)) } } }
编译错误信息
unable to resolve class com.mongodb.MongoClient @ line 22, column 1. @Grapes([ ^ unable to resolve class com.mongodb.client.MongoCollection @ line 26, column 1. import com.mongodb.client.MongoCollection; ^ unable to resolve class com.mongodb.client.MongoCursor @ line 27, column 1. import com.mongodb.client.MongoCursor; ^ unable to resolve class org.bson.Document @ line 28, column 1. import org.bson.Document; ^ unable to resolve class HTTPRequest @ line 60, column 2. public static HTTPRequest request ^ unable to resolve class Cookie @ line 63, column 21. public static List<Cookie> cookies = [] ^ unable to resolve class HTTPRequest @ line 72, column 13. request = new HTTPRequest() ^ HTTPResponse response = request.GET("http://127.0.0.1:8030/feed-server/feed/" + {userId} + "?last_post_id=" + last_post_ids.nextInt(5), params) ^ 8 errors at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:295) at org.codehaus.groovy.control.CompilationUnit$ISourceUnitOperation.doPhaseOperation(CompilationUnit.java:914) at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:627) at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:389) at groovy.lang.GroovyClassLoader.lambda$parseClass$3(GroovyClassLoader.java:332) at org.codehaus.groovy.runtime.memoize.StampedCommonCache.compute(StampedCommonCache.java:163) at org.codehaus.groovy.runtime.memoize.StampedCommonCache.getAndPut(StampedCommonCache.java:154) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:330) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:314) at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:244) at net.grinder.scriptengine.groovy.GroovyScriptEngine.<init>(GroovyScriptEngine.java:64)
修复方案及修正后的脚本
核心修复点
- MongoDB依赖处理:nGrinder环境下
@Grab注解通常无法自动拉取依赖,需手动下载mongo-java-driver-3.12.12.jar及其依赖的bson-3.12.12.jar,放入nGrinder安装目录的lib文件夹下,重启nGrinder服务。 - Mongo客户端初始化修正:3.12.12版本的驱动使用
MongoClient而非MongoClients,需修改初始化代码。 - 数据加载时机调整:将MongoDB数据加载移到
BeforeThread中,避免每次用例执行都重复查询数据库,提升性能。 - 随机取值代码修正:使用Random类生成数组索引,随机获取
last_post_id。 - 字符串拼接修正:移除闭包写法
{userId},直接使用变量拼接。 - 导入Random类:添加
java.util.Random的导入,避免编译错误。
修正后的完整脚本
import static net.grinder.script.Grinder.grinder import static org.junit.Assert.* import static org.hamcrest.Matchers.* import net.grinder.script.GTest import net.grinder.script.Grinder import net.grinder.scriptengine.groovy.junit.GrinderRunner import net.grinder.scriptengine.groovy.junit.annotation.BeforeProcess import net.grinder.scriptengine.groovy.junit.annotation.BeforeThread import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import java.util.Random import org.ngrinder.http.HTTPRequest import org.ngrinder.http.HTTPRequestControl import org.ngrinder.http.HTTPResponse import org.ngrinder.http.cookie.Cookie import org.ngrinder.http.cookie.CookieManager import com.mongodb.MongoClient import com.mongodb.client.MongoCollection import org.bson.Document /** * nGrinder接口测试脚本:随机获取MongoDB中的post_id作为请求参数 * * @author admin */ @RunWith(GrinderRunner) class TestRunner { public static GTest test public static HTTPRequest request public static Map<String, String> headers = [:] public static Map<String, Object> params = [:] public static List<Cookie> cookies = [] public static List<String> last_post_ids = [] public static final String db_name = "instaclone_post" public static final String collection_name = "post" public static Random rand = new Random() @BeforeProcess public static void beforeProcess() { HTTPRequestControl.setConnectionTimeout(300000) test = new GTest(1, "127.0.0.1") request = new HTTPRequest() grinder.logger.info("before process.") } @BeforeThread public void beforeThread() { test.record(this, "test") grinder.statistics.delayReports = true grinder.logger.info("before thread.") // 线程初始化时查询一次MongoDB,避免每次用例重复查询 MongoClient mongoClient = new MongoClient("localhost", 27017) grinder.logger.info("Connected to MongoDB successfully") MongoCollection<Document> collection = mongoClient.getDatabase(db_name).getCollection(collection_name) def documents = collection.find(new Document(), new Document("_id", 1)).into([]) for (document in documents) { def postId = document.get("_id").toString() last_post_ids.add(postId) grinder.logger.info("Loaded post_id: {}", postId) } mongoClient.close() } @Before public void before() { request.setHeaders(headers) CookieManager.addCookies(cookies) grinder.logger.info("before. init headers and cookies") } @Test public void test() { // 生成随机userId int userId = Math.abs(rand.nextInt() % 10) + 1 // 随机获取last_post_id String lastPostId = last_post_ids.isEmpty() ? "" : last_post_ids.get(rand.nextInt(last_post_ids.size())) // 拼接请求URL String url = "http://127.0.0.1:8030/feed-server/feed/${userId}?last_post_id=${lastPostId}" HTTPResponse response = request.GET(url, params) if (response.statusCode == 301 || response.statusCode == 302) { grinder.logger.warn("Warning. The response code was {}.", response.statusCode) } else { assertThat(response.statusCode, is(200)) } } }
内容的提问来源于stack exchange,提问作者happy
相关产品推荐
相关产品推荐

