Skip to content

Error when used on MySQL with transactional_fixtures enabled in RSpec #55

@Envek

Description

@Envek

When Rails application is tested with RSpec and transactional_fixtures are enabled:

RSpec.configure do |config|
  config.extend WithModel
  config.use_transactional_fixtures = true
end

RSpec.describe "TestModel" do
  with_model :TestModel do
    table do |t|
      t.string :title
    end
  end

  it "works" do
    expect(TestModel.create!(title: "Whatever")).to be_present
  end
end

Following error is thrown when a with_model record is created:

SAVEPOINT active_record_1 does not exist

Test logs:

TRANSACTION (0.1ms)  BEGIN
 (21.5ms)  CREATE TABLE `with_model_test_models_178402_9300` (`id` bigint NOT NULL AUTO_INCREMENT PRIMARY KEY, `title` varchar(255))
TRANSACTION (0.3ms)  SAVEPOINT active_record_1
TestModel Create (2.0ms)  INSERT INTO `with_model_test_models_178402_9300` (`title`) VALUES ('Whatever')
TRANSACTION (0.3ms)  RELEASE SAVEPOINT active_record_1
TRANSACTION (0.1ms)  ROLLBACK TO SAVEPOINT active_record_1
 (4.2ms)  DROP TABLE `with_model_test_models_178402_9300`

Note that ROLLBACK TO SAVEPOINT active_record_1 used after releasing that same savepoint instead of just ROLLBACK of the whole transaction.

Correct logs from PostgreSQL example
TRANSACTION (0.2ms)  BEGIN
 (3.4ms)  CREATE TABLE "with_model_test_models_182673_6320" ("id" bigserial primary key, "title" character varying)
TRANSACTION (0.5ms)  SAVEPOINT active_record_1
TestModel Create (1.2ms)  INSERT INTO "with_model_test_models_182673_6320" ("title") VALUES ($1) RETURNING "id"  [["title", "Whatever"]]
TRANSACTION (0.4ms)  RELEASE SAVEPOINT active_record_1
 (0.8ms)  DROP TABLE "with_model_test_models_182673_6320"
TRANSACTION (0.4ms)  ROLLBACK

Environment:

Gem version: 2.2.0
Rails version: 7.2 and 8.0, both mysql2 and trilogy adapters.

Reproduction steps:

  1. Run MySQL server. E.g. with Docker:

    docker run --rm -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -e MYSQL_DATABASE=test -p 3306:3306 mysql:latest
  2. Run reproduction executable test case: https://gist.github.com/Envek/1e152e913787554379ec2834cdeaf169

    wget https://gist.github.com/Envek/1e152e913787554379ec2834cdeaf169/raw/09e2bc0a4501322842e5462fdb222d7475ea551e/with_model_mysql_spec.rb
    ruby with_model_mysql_spec.rb  

Workaround:

Replace with_model with manual table and model creation.

Manual table and model creation.
before(:context) do # rubocop:disable RSpec/BeforeAfterAll
  ActiveRecord::Schema.define do
    drop_table :dynamodb_attrs, if_exists: true
    create_table :test_models do |t|
      t.string :title
    end
  end
end

after(:context) do # rubocop:disable RSpec/BeforeAfterAll
  ActiveRecord::Schema.define do
    drop_table :test_models, if_exists: true
  end
end

# Stub the constant for each example
before do
  stub_const("TestModel", Class.new(ActiveRecord::Base) do
    self.table_name = "test_models"
  end)
end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions