@stryker-mutator/core
Version:
The extendable JavaScript mutation testing framework
182 lines • 9.9 kB
JavaScript
import { factory, testInjector } from '@stryker-mutator/test-helpers';
import { expect } from 'chai';
import sinon from 'sinon';
import { commonTokens } from '@stryker-mutator/api/plugin';
import { LogConfigurator } from '../../src/logging/index.js';
import { Stryker } from '../../src/stryker.js';
import { PrepareExecutor, MutantInstrumenterExecutor, DryRunExecutor, MutationTestExecutor } from '../../src/process/index.js';
import { coreTokens } from '../../src/di/index.js';
import { ConfigError } from '../../src/errors.js';
import { TemporaryDirectory } from '../../src/utils/temporary-directory.js';
describe(Stryker.name, () => {
let sut;
let shutdownLoggingStub;
let injectorMock;
let cliOptions;
let mutantResults;
let loggerMock;
let temporaryDirectoryMock;
let getLoggerStub;
let prepareExecutorMock;
let mutantInstrumenterExecutorMock;
let dryRunExecutorMock;
let mutationTestExecutorMock;
beforeEach(() => {
injectorMock = factory.injector();
loggerMock = factory.logger();
getLoggerStub = sinon.stub();
mutantResults = [];
temporaryDirectoryMock = sinon.createStubInstance(TemporaryDirectory);
prepareExecutorMock = sinon.createStubInstance(PrepareExecutor);
mutantInstrumenterExecutorMock = sinon.createStubInstance(MutantInstrumenterExecutor);
dryRunExecutorMock = sinon.createStubInstance(DryRunExecutor);
mutationTestExecutorMock = sinon.createStubInstance(MutationTestExecutor);
injectorMock.injectClass
.withArgs(PrepareExecutor)
.returns(prepareExecutorMock)
.withArgs(MutantInstrumenterExecutor)
.returns(mutantInstrumenterExecutorMock)
.withArgs(DryRunExecutor)
.returns(dryRunExecutorMock)
.withArgs(MutationTestExecutor)
.returns(mutationTestExecutorMock);
injectorMock.resolve
.withArgs(commonTokens.getLogger)
.returns(getLoggerStub)
.withArgs(coreTokens.temporaryDirectory)
.returns(temporaryDirectoryMock)
.withArgs(commonTokens.options)
.returns(testInjector.options);
getLoggerStub.returns(loggerMock);
prepareExecutorMock.execute.resolves(injectorMock);
mutantInstrumenterExecutorMock.execute.resolves(injectorMock);
dryRunExecutorMock.execute.resolves(injectorMock);
mutationTestExecutorMock.execute.resolves(mutantResults);
cliOptions = {};
shutdownLoggingStub = sinon.stub(LogConfigurator, 'shutdown');
});
describe('runMutationTest()', () => {
beforeEach(() => {
sut = new Stryker(cliOptions, () => injectorMock);
});
it('should execute the preparations', async () => {
await sut.runMutationTest();
expect(prepareExecutorMock.execute).calledOnce;
});
it('should execute the mutant instrumenter', async () => {
await sut.runMutationTest();
expect(mutantInstrumenterExecutorMock.execute).calledOnce;
});
it('should execute the dry run', async () => {
await sut.runMutationTest();
expect(dryRunExecutorMock.execute).calledOnce;
});
it('should execute actual mutation testing', async () => {
await sut.runMutationTest();
expect(mutationTestExecutorMock.execute).calledOnce;
});
it('should provide the cli options to the prepare executor', async () => {
cliOptions.logLevel = "trace" /* LogLevel.Trace */;
const expectedCliOptions = { ...cliOptions };
await sut.runMutationTest();
sinon.assert.calledWith(prepareExecutorMock.execute, expectedCliOptions);
});
it('should reject when prepare rejects', async () => {
const expectedError = new Error('expected error for testing');
prepareExecutorMock.execute.rejects(expectedError);
await expect(sut.runMutationTest()).rejectedWith(expectedError);
});
it('should not log a stack trace for a config error', async () => {
const expectedError = new ConfigError('foo should be bar');
prepareExecutorMock.execute.rejects(expectedError);
await expect(sut.runMutationTest()).rejected;
expect(loggerMock.error).calledWithExactly('foo should be bar');
});
it('should reject when execute the mutant instrumenter rejects', async () => {
const expectedError = new Error('expected error for testing');
mutationTestExecutorMock.execute.rejects(expectedError);
await expect(sut.runMutationTest()).rejectedWith(expectedError);
});
it('should reject when execute the dry run rejects', async () => {
const expectedError = new Error('expected error for testing');
dryRunExecutorMock.execute.rejects(expectedError);
await expect(sut.runMutationTest()).rejectedWith(expectedError);
});
it('should reject when execute actual mutation testing rejects', async () => {
const expectedError = new Error('expected error for testing');
mutationTestExecutorMock.execute.rejects(expectedError);
await expect(sut.runMutationTest()).rejectedWith(expectedError);
});
it('should log the error when prepare rejects unexpectedly', async () => {
const expectedError = new Error('expected error for testing');
prepareExecutorMock.execute.rejects(expectedError);
await expect(sut.runMutationTest()).rejected;
expect(loggerMock.error).calledWith('Unexpected error occurred while running Stryker', expectedError);
});
it('should disable `removeDuringDisposal` on the temp dir when dry run rejects', async () => {
dryRunExecutorMock.execute.rejects(new Error('expected error for testing'));
await expect(sut.runMutationTest()).rejected;
expect(getLoggerStub).calledWith('Stryker');
expect(loggerMock.debug).calledWith('Not removing the temp dir because an error occurred');
expect(temporaryDirectoryMock.removeDuringDisposal).false;
});
it('should not disable `removeDuringDisposal` on the temp dir when dry run rejects and cleanTempDir is set to `always`', async () => {
dryRunExecutorMock.execute.rejects(new Error('expected error for testing'));
testInjector.options.cleanTempDir = 'always';
await expect(sut.runMutationTest()).rejected;
expect(temporaryDirectoryMock.removeDuringDisposal).not.false;
});
it('should log the error when dry run rejects unexpectedly', async () => {
const expectedError = new Error('expected error for testing');
dryRunExecutorMock.execute.rejects(expectedError);
await expect(sut.runMutationTest()).rejected;
expect(getLoggerStub).calledWith('Stryker');
expect(loggerMock.error).calledWith('Unexpected error occurred while running Stryker', expectedError);
});
it('should log a help message when log level "trace" is not enabled', async () => {
const expectedError = new Error('expected error for testing');
loggerMock.isTraceEnabled.returns(false);
dryRunExecutorMock.execute.rejects(expectedError);
await expect(sut.runMutationTest()).rejected;
[
'This might be a known problem with a solution documented in our troubleshooting guide.',
'You can find it at https://stryker-mutator.io/docs/stryker-js/troubleshooting/',
'Still having trouble figuring out what went wrong? Try `npx stryker run --fileLogLevel trace --logLevel debug` to get some more info.',
].forEach((m) => expect(loggerMock.info).calledWith(m));
});
it('should not log a help message when log level "trace" is enabled', async () => {
const expectedError = new Error('expected error for testing');
loggerMock.isTraceEnabled.returns(true);
dryRunExecutorMock.execute.rejects(expectedError);
await expect(sut.runMutationTest()).rejected;
[
'This might be a known problem with a solution documented in our troubleshooting guide.',
'You can find it at https://stryker-mutator.io/docs/stryker-js/troubleshooting/',
].forEach((m) => expect(loggerMock.info).calledWith(m));
});
it('should dispose the injector', async () => {
await sut.runMutationTest();
expect(injectorMock.dispose).called;
});
it('should dispose also on a rejection injector', async () => {
prepareExecutorMock.execute.rejects(new Error('expected error'));
await expect(sut.runMutationTest()).rejected;
expect(injectorMock.dispose).called;
});
it('should shut down the logging server', async () => {
await sut.runMutationTest();
expect(shutdownLoggingStub).called;
});
it('should dispose the injector when actual mutation testing rejects', async () => {
mutationTestExecutorMock.execute.rejects(new Error('Expected error for testing'));
await expect(sut.runMutationTest()).rejected;
expect(injectorMock.dispose).called;
});
it('should shut down the logging server when actual mutation testing rejects', async () => {
mutationTestExecutorMock.execute.rejects(new Error('Expected error for testing'));
await expect(sut.runMutationTest()).rejected;
expect(shutdownLoggingStub).called;
});
});
});
//# sourceMappingURL=stryker.spec.js.map