Извините за создание нового вопроса, я не смог найти вопрос, касающийся этого вопроса.
У меня возникли трудности с тестированием моей инъекции зависимостей с использованием мокко и экспериментальных декораторов es6+, транспилированных с помощью babel. Декоратор свойств класса вызывается раньше, чем это должно было быть.
инъекции.test.js (тест мокко, с использованием --require babel-register
)
import * as DependencyInjection from '../build/decorators/DependencyInjection';
@DependencyInjection.Injectable(service => service.injected = true)
class SampleService {
property = 'default';
constructor(property, ...data) {
this.property = property || this.property;
}
}
class Dependant {
/** @type {SampleService} */
@DependencyInjection.Inject(SampleService)
sampleService;
}
describe('dependency injection', () => {
describe('is decoratored as injectable', () => {
it('should be injectable', done => done(SampleService.injectable ? void 0 : new Error('Injectable is not set')));
it('should contain a predicate', done => done(SampleService.predicate ? void 0 : new Error('Predicate is not set')));
});
describe('inject injectable', () => {
it ('should inject the injectable provider', done => {
const dependant = new Dependant();
done(!!dependant.sampleService ? void 0 : new Error('Injectable provider was not injected'));
})
});
});
При запуске теста украшенный класс трансформируется как задумано. Однако свойство sampleService
экземпляра Dependant
, созданного во втором тесте, не определено.
Рассматриваемый декоратор следует вызывать/вызывать после создания экземпляра класса, но декоратор вызывается при определении класса и оформлении свойства. Ожидаемое поведение сохраняется при использовании TypeScript
.
Ниже я перечислил (упрощенные) декораторы и мою конфигурацию babel.
.babelrc
{
"presets": [
"env",
"stage-0",
"es2017"
],
"plugins": [
"syntax-decorators",
"transform-decorators-legacy",
["transform-runtime", {
"polyfill": false,
"regenerator": true
}]
]
}
экспортированный декоратор Inject (таргетинг class property
):
exports.Inject = (typeFunction, ...data) => {
return function (target, propertyName) {
try {
const injected = target[propertyName] = new typeFunction(data);
if ('predicate' in typeFunction && typeof typeFunction.predicate === 'function') {
typeFunction.predicate(injected);
}
}
catch (err) {
throw new Error(err.message || err);
}
};
};
экспортированный декоратор Injectable (нацелен на class
):
exports.Injectable = (predicate) => {
return function (target) {
const provider = target;
provider.injectable = true;
if (predicate && typeof predicate === 'function') {
provider.predicate = predicate;
}
};
};