Skip to content

Commit

Permalink
Add the possibility to predefine objects and states for unit tests
Browse files Browse the repository at this point in the history
Fixes #14
  • Loading branch information
AlCalzone committed Mar 18, 2019
1 parent a3a1af7 commit 474325c
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 19 deletions.
33 changes: 28 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,26 @@ tests.unit(path.join(__dirname, ".."), {
"{CONTROLLER_DIR}/lib/tools.js": {},
},

// Define your own tests inside defineAdditionalTests
defineAdditionalTests() {
it("works", () => {
// see below how these could look like
});
// optionally define an array of objects that need to be present in the objects DB
// instance objects from io-package.json are pre-loaded by default
predefinedObjects: [
{
_id: "test.0.object1",
common: { /* ... */ },
native: { /* ... */ },
},
{
_id: "test.0.object2",
common: { /* ... */ },
native: { /* ... */ },
}
],

// Optionally define which states need to exist in the states DB
// You can set all properties that are usually available on a state
predefinedStates: {
"test.0.object1": { val: true, ack: false },
"test.0.object2": { val: 2, ack: false, ts: 1 },
},

// If the startup tests need require specific behavior of the mocks
Expand All @@ -76,6 +91,14 @@ tests.unit(path.join(__dirname, ".."), {
adapter.objects.getUserGroup.returns("a string");
}

// Define your own tests inside defineAdditionalTests.
// If you need predefined objects etc. here, you need to take care of it yourself
defineAdditionalTests() {
it("works", () => {
// see below how these could look like
});
},

});
```

Expand Down
6 changes: 4 additions & 2 deletions build/tests/unit/harness/startMockAdapter.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ export interface StartMockAdapterOptions {
compact?: boolean;
/** The adapter config */
config?: Record<string, any>;
/** An array of instance objects that should be populated before starting the adapter */
instanceObjects?: ioBroker.Object[];
/** An array of objects that should be populated before starting the adapter */
predefinedObjects?: ioBroker.Object[];
/** A dictionary of states that should be populated before starting the adapter */
predefinedStates?: Record<string, ioBroker.State>;
/** Mocks for loaded modules. This should be a dictionary of module name to module.exports */
additionalMockedModules?: Record<string, any>;
/** Allows you to modifiy the behavior of predefined mocks in the predefined methods */
Expand Down
9 changes: 6 additions & 3 deletions build/tests/unit/harness/startMockAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,12 @@ function startMockAdapter(adapterMainFile, options = {}) {
return __awaiter(this, void 0, void 0, function* () {
// Setup the mocks
const databaseMock = new mockDatabase_1.MockDatabase();
// If instance objects are defined, populate the database mock with them
if (options.instanceObjects && options.instanceObjects.length) {
databaseMock.publishObjects(...options.instanceObjects);
// If objects and/or states are predefined, populate the database mock with them
if (options.predefinedObjects && options.predefinedObjects.length) {
databaseMock.publishObjects(...options.predefinedObjects);
}
if (options.predefinedStates) {
databaseMock.publishStates(options.predefinedStates);
}
let adapterMock;
const adapterCoreMock = mockAdapterCore_1.mockAdapterCore(databaseMock, {
Expand Down
5 changes: 5 additions & 0 deletions build/tests/unit/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/// <reference types="iobroker" />
import { StartMockAdapterOptions } from "./harness/startMockAdapter";
import { MockAdapter } from "./mocks/mockAdapter";
import { MockDatabase } from "./mocks/mockDatabase";
Expand All @@ -6,6 +7,10 @@ export interface TestAdapterOptions {
additionalMockedModules?: StartMockAdapterOptions["additionalMockedModules"];
/** Change the default test timeout of 15000ms for the startup tests */
startTimeout?: number;
/** An array of objects that should be populated before starting the adapter */
predefinedObjects?: ioBroker.Object[];
/** A dictionary of states that should be populated before starting the adapter */
predefinedStates?: Record<string, ioBroker.State>;
/** Allows you to define additional tests */
defineAdditionalTests?: () => void;
/** Allows you to modifiy the behavior of predefined mocks in the predefined methods */
Expand Down
12 changes: 10 additions & 2 deletions build/tests/unit/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ function testAdapterWithMocks(adapterDir, options = {}) {
this.timeout(options.startTimeout);
const { adapterMock, databaseMock, processExitCode, terminateReason } = yield startMockAdapter_1.startMockAdapter(mainFilename, {
config: adapterConfig,
instanceObjects,
predefinedObjects: [
...instanceObjects,
...(options.predefinedObjects || []),
],
predefinedStates: options.predefinedStates,
additionalMockedModules: options.additionalMockedModules,
defineMockBehavior: options.defineMockBehavior,
adapterDir,
Expand All @@ -68,7 +72,11 @@ function testAdapterWithMocks(adapterDir, options = {}) {
const { adapterMock, databaseMock, processExitCode, terminateReason } = yield startMockAdapter_1.startMockAdapter(mainFilename, {
compact: true,
config: adapterConfig,
instanceObjects,
predefinedObjects: [
...instanceObjects,
...(options.predefinedObjects || []),
],
predefinedStates: options.predefinedStates,
additionalMockedModules: options.additionalMockedModules,
defineMockBehavior: options.defineMockBehavior,
adapterDir,
Expand Down
1 change: 1 addition & 0 deletions build/tests/unit/mocks/mockDatabase.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export declare class MockDatabase {
deleteObject(objID: string): void;
publishState(id: string, state: Partial<ioBroker.State> | null | undefined): void;
deleteState(id: string): void;
publishStates(states: Record<string, Partial<ioBroker.State> | null | undefined>): void;
hasObject(id: string): boolean;
hasObject(namespace: string, id: string): boolean;
getObject(id: string): ioBroker.Object | undefined;
Expand Down
5 changes: 5 additions & 0 deletions build/tests/unit/mocks/mockDatabase.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ class MockDatabase {
deleteState(id) {
this.states.delete(id);
}
publishStates(states) {
for (const id of Object.keys(states)) {
this.publishState(id, states[id]);
}
}
hasObject(namespaceOrId, id) {
id = namespaceOrId + (id ? "." + id : "");
return this.objects.has(id);
Expand Down
15 changes: 10 additions & 5 deletions src/tests/unit/harness/startMockAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ export interface StartMockAdapterOptions {
compact?: boolean;
/** The adapter config */
config?: Record<string, any>;
/** An array of instance objects that should be populated before starting the adapter */
instanceObjects?: ioBroker.Object[];
/** An array of objects that should be populated before starting the adapter */
predefinedObjects?: ioBroker.Object[];
/** A dictionary of states that should be populated before starting the adapter */
predefinedStates?: Record<string, ioBroker.State>;
/** Mocks for loaded modules. This should be a dictionary of module name to module.exports */
additionalMockedModules?: Record<string, any>;
/** Allows you to modifiy the behavior of predefined mocks in the predefined methods */
Expand All @@ -37,9 +39,12 @@ export async function startMockAdapter(adapterMainFile: string, options: StartMo

// Setup the mocks
const databaseMock = new MockDatabase();
// If instance objects are defined, populate the database mock with them
if (options.instanceObjects && options.instanceObjects.length) {
databaseMock.publishObjects(...options.instanceObjects);
// If objects and/or states are predefined, populate the database mock with them
if (options.predefinedObjects && options.predefinedObjects.length) {
databaseMock.publishObjects(...options.predefinedObjects);
}
if (options.predefinedStates) {
databaseMock.publishStates(options.predefinedStates);
}
let adapterMock: MockAdapter | undefined;
const adapterCoreMock = mockAdapterCore(databaseMock, {
Expand Down
16 changes: 14 additions & 2 deletions src/tests/unit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export interface TestAdapterOptions {
additionalMockedModules?: StartMockAdapterOptions["additionalMockedModules"];
/** Change the default test timeout of 15000ms for the startup tests */
startTimeout?: number;
/** An array of objects that should be populated before starting the adapter */
predefinedObjects?: ioBroker.Object[];
/** A dictionary of states that should be populated before starting the adapter */
predefinedStates?: Record<string, ioBroker.State>;
/** Allows you to define additional tests */
defineAdditionalTests?: () => void;
/** Allows you to modifiy the behavior of predefined mocks in the predefined methods */
Expand Down Expand Up @@ -57,7 +61,11 @@ export function testAdapterWithMocks(adapterDir: string, options: TestAdapterOpt

const { adapterMock, databaseMock, processExitCode, terminateReason } = await startMockAdapter(mainFilename, {
config: adapterConfig,
instanceObjects,
predefinedObjects: [
...instanceObjects,
...(options.predefinedObjects || []),
],
predefinedStates: options.predefinedStates,
additionalMockedModules: options.additionalMockedModules,
defineMockBehavior: options.defineMockBehavior,
adapterDir,
Expand All @@ -78,7 +86,11 @@ export function testAdapterWithMocks(adapterDir: string, options: TestAdapterOpt
const { adapterMock, databaseMock, processExitCode, terminateReason } = await startMockAdapter(mainFilename, {
compact: true,
config: adapterConfig,
instanceObjects,
predefinedObjects: [
...instanceObjects,
...(options.predefinedObjects || []),
],
predefinedStates: options.predefinedStates,
additionalMockedModules: options.additionalMockedModules,
defineMockBehavior: options.defineMockBehavior,
adapterDir,
Expand Down
5 changes: 5 additions & 0 deletions src/tests/unit/mocks/mockDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ export class MockDatabase {
public deleteState(id: string) {
this.states.delete(id);
}
public publishStates(states: Record<string, Partial<ioBroker.State> | null | undefined>) {
for (const id of Object.keys(states)) {
this.publishState(id, states[id]);
}
}

public hasObject(id: string): boolean;
public hasObject(namespace: string, id: string): boolean;
Expand Down

0 comments on commit 474325c

Please sign in to comment.