I have made a React Native app which uses the Realm database. Opening this app and testing it manually does not result in any errors.
I have written tests for the Realm database, such as:
test("Create record in example table", () => {
realm.write(() => {
realm.create("ExampleTable", { "id": 1, "name": "Example", "notes": "Example Notes" });
});
const exampleRecord = realm.objects("ExampleTable")[0];
expect(exampleRecord.id).toBe(1);
expect(exampleRecord.name).toBe("Example");
expect(exampleRecord.notes).toBe("Example Notes");
});
These tests pass.
I have also written snapshot tests for different screens:
test("index.js Test", async () => {
const snapshot = renderer.create(<App />);
const snapshotJSON = snapshot.toJSON();
expect(snapshotJSON).toMatchSnapshot();
snapshot.unmount();
});
These tests fail. The error is:
Realm at path '/home/runner/work/app-name/app-name/default.realm' already opened on current thread with different schema.
In order to fix the error, I have attempted to write multiple different lines in the beforeEach()
and afterEach()
code blocks of the test file. However, these have not worked. For example, I have written the lines jest.clearAllMocks();
and Realm.delete()
in the afterEach()
code block. Through research, I have found the error may be because the tests are run in conjunction and Realm does not allow this. However, I have found no way to attempt to run the tests individually.
The only errors I have gotten besides these errors are:
● Console
console.error
The above error occurred in the <CreateWorkout> component:
at CreateWorkout (/home/runner/work/fitness-logger/fitness-logger/app/screens/create-workout/create-workout.js:10:63)
113 | const snapshotJSON = snapshot.toJSON();
114 | expect(snapshotJSON).toMatchSnapshot();
> 115 | snapshot.unmount();
| ^
To run the tests, I am using the command: npx jest --runInBand --detectOpenHandles --forceExit
Through research, I have found that I may need to mock the Realm database, although I am unsure how to do this. I am not using any Realm functions in my test file, although screens that I am taking snapshot tests of use the Realm database and use Realm functions
I have written the following mock in the test file:
jest.mock("realm", () => {
const mockObjects = jest.fn(() => {
const results = [];
results.filtered = jest.fn(() => { return results; });
return results;
});
function MockRealm() {
return {
"objects": mockObjects,
"write": jest.fn(),
"create": jest.fn(),
"deleteAll": jest.fn(),
"close": jest.fn(),
"addListener": jest.fn(),
"removeListener": jest.fn(),
};
}
MockRealm.open = jest.fn();
MockRealm.schema = [
{
"name": "Table",
"properties": {
"id": "int",
"property": "string",
},
"primaryKey": "id",
}
];
MockRealm.deleteRealmIfMigrationNeeded = true;
return MockRealm;
});
This stops the tests from failing. However, the tests still return the error from my try catch
block: Failed to get data from schema
. Moving this mock code into its own file in the __mocks__
directory causes the tests to fail.
I have made a React Native app which uses the Realm database. Opening this app and testing it manually does not result in any errors.
I have written tests for the Realm database, such as:
test("Create record in example table", () => {
realm.write(() => {
realm.create("ExampleTable", { "id": 1, "name": "Example", "notes": "Example Notes" });
});
const exampleRecord = realm.objects("ExampleTable")[0];
expect(exampleRecord.id).toBe(1);
expect(exampleRecord.name).toBe("Example");
expect(exampleRecord.notes).toBe("Example Notes");
});
These tests pass.
I have also written snapshot tests for different screens:
test("index.js Test", async () => {
const snapshot = renderer.create(<App />);
const snapshotJSON = snapshot.toJSON();
expect(snapshotJSON).toMatchSnapshot();
snapshot.unmount();
});
These tests fail. The error is:
Realm at path '/home/runner/work/app-name/app-name/default.realm' already opened on current thread with different schema.
In order to fix the error, I have attempted to write multiple different lines in the beforeEach()
and afterEach()
code blocks of the test file. However, these have not worked. For example, I have written the lines jest.clearAllMocks();
and Realm.delete()
in the afterEach()
code block. Through research, I have found the error may be because the tests are run in conjunction and Realm does not allow this. However, I have found no way to attempt to run the tests individually.
The only errors I have gotten besides these errors are:
● Console
console.error
The above error occurred in the <CreateWorkout> component:
at CreateWorkout (/home/runner/work/fitness-logger/fitness-logger/app/screens/create-workout/create-workout.js:10:63)
113 | const snapshotJSON = snapshot.toJSON();
114 | expect(snapshotJSON).toMatchSnapshot();
> 115 | snapshot.unmount();
| ^
To run the tests, I am using the command: npx jest --runInBand --detectOpenHandles --forceExit
Through research, I have found that I may need to mock the Realm database, although I am unsure how to do this. I am not using any Realm functions in my test file, although screens that I am taking snapshot tests of use the Realm database and use Realm functions
I have written the following mock in the test file:
jest.mock("realm", () => {
const mockObjects = jest.fn(() => {
const results = [];
results.filtered = jest.fn(() => { return results; });
return results;
});
function MockRealm() {
return {
"objects": mockObjects,
"write": jest.fn(),
"create": jest.fn(),
"deleteAll": jest.fn(),
"close": jest.fn(),
"addListener": jest.fn(),
"removeListener": jest.fn(),
};
}
MockRealm.open = jest.fn();
MockRealm.schema = [
{
"name": "Table",
"properties": {
"id": "int",
"property": "string",
},
"primaryKey": "id",
}
];
MockRealm.deleteRealmIfMigrationNeeded = true;
return MockRealm;
});
This stops the tests from failing. However, the tests still return the error from my try catch
block: Failed to get data from schema
. Moving this mock code into its own file in the __mocks__
directory causes the tests to fail.
From your description it definitely looks like it's an issue with running multiple tests in parallel. If you are using jest, you can use the --runInBand
flag to run them all sequentially.
Mock Realm in the testing file using the following code:
jest.mock("realm", () => {
const mockRealm = {
"objects": jest.fn(() => {
const results = [];
results.filtered = jest.fn(() => { return results; });
results.map = jest.fn(() => { return []; });
return results;
}),
"write": jest.fn((callback) => { return callback(); }),
"create": jest.fn(),
"deleteAll": jest.fn(),
"close": jest.fn(),
"addListener": jest.fn(),
"removeListener": jest.fn(),
};
mockRealm.open = jest.fn().mockResolvedValue(mockRealm);
mockRealm.schema = [
{
"name": "Table",
"properties": {
"id": "int",
"property": "string",
},
"primaryKey": "id",
}
];
mockRealm.deleteRealmIfMigrationNeeded = true;
return jest.fn(() => { return mockRealm; });
});
Write the snapshot tests using act
from react-test-renderer
:
test("index.js Test", async () => {
const snapshot = renderer.create(<App/>);
let snapshot;
await act(async () => {
snapshot = renderer.create(<App/>);
});
const snapshotJSON = snapshot.toJSON();
expect(snapshotJSON).toMatchSnapshot();
snapshot.unmount();
});