k6

xk6-sql extension: db connection cannot be passed from setup() stage


I had a test case where there were 2 scenarios to insert data to MySQL tables via xk6-sql extension. Here is the structure of my code.

main.js

import sql from "k6/x/sql";
export { runtest1 } from "./runtest1.js";
export { runtest2 } from "./runtest2.js";

const testConfig = JSON.parse(open("./conf.json"));
export const options = Object.assign(
  {
    insecureSkipTLSVerify: false,
  },
  testConfig
);

export function setup() {
  const db = sql.open("mysql", "root:@tcp(127.0.0.1:3306)/testing");
  console.log(db);
  return db;
}

export default function () {
  console.log("running test cases...");
}

export function teardown(data) {
  data.db.close();
}

runTest1.js

export function runtest1(data) {
  data.db.exec(
    `INSERT INTO cats1 (name, breed, age) VALUES ('test1-2', 'Doodle', 1)`
  );
}

runTest2.js

export function runtest2(data) {
  data.db.exec(
    `INSERT INTO cats1 (name, breed, age) VALUES ('test2-2', 'Doodle', 2)`
  );
}

config.json

{
  "scenarios": {
    "scenario1": {
      "executor": "shared-iterations",
      "vus": 1,
      "iterations": 1,
      "exec": "runtest1"
    },
    "scenario2": {
      "executor": "shared-iterations",
      "vus": 1,
      "iterations": 1,
      "exec": "runtest2"
    }
  }
}

I received the TypeError: Cannot read property ‘exec’ of undefined or null from the 2 scenarios. Can anyone explain why the db connection was not able to passed from setup()?


Solution

  • setup() can only return JSON data, not arbitrary JavaScript objects.

    You must open the connection in the init context (outside of any function), as is shown in the example in the README:

    import sql from 'k6/x/sql';
    
    const db = sql.open("sqlite3", "./test.db");
    
    export function setup() {
      db.exec(`CREATE TABLE IF NOT EXISTS keyvalues (
               id integer PRIMARY KEY AUTOINCREMENT,
               key varchar NOT NULL,
               value varchar);`);
    }
    
    export function teardown() {
      db.close();
    }
    

    So in your case:

    import sql from "k6/x/sql";
    export { runtest1 } from "./runtest1.js";
    export { runtest2 } from "./runtest2.js";
    
    const testConfig = JSON.parse(open("./conf.json"));
    export const options = Object.assign(
      {
        insecureSkipTLSVerify: false,
      },
      testConfig
    );
    
    const db = sql.open("mysql", "root:@tcp(127.0.0.1:3306)/testing");
    
    export function teardown(data) {
      data.db.close();
    }
    
    export default function () {
      console.log("running test cases...");
    }