Skip to content

Commit

Permalink
Fix overwriting providers
Browse files Browse the repository at this point in the history
Signed-off-by: Arda TANRIKULU <[email protected]>
  • Loading branch information
ardatan committed Mar 14, 2019
1 parent 992406c commit ec07aed
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 41 deletions.
44 changes: 7 additions & 37 deletions docs/introduction/test-your-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export const UserModule = new GraphQLModule({
}
type Query {
me: User
userById(id: String!): User
}
`,
Expand All @@ -40,56 +39,27 @@ export const UserModule = new GraphQLModule({
username: user => user.username,
},
Query: {
me: (root, args, { currentUser }) => currentUser,
userById: (root, { id }, injector) =>
injector.get(UsersProvider).getUserById(id),
},
},
});
```

You can mock context and providers by importing the existing module together with resolvers into a new testing module like below;
You can mock providers by overwriting the existing provider definitions;

tests/user.module.spec.ts
```typescript
import { UserModule } from '../modules/user/user.module';
import { execute } from 'graphql';
describe('UserModule', async () => {
it('FieldResolver of Query: me', async () => {
const { schema, context } = new GraphQLModule({
imports: [UserModule],
resolvers: UserModule.resolvers,
context: { currentUser: { id: 'ID', username: 'USERNAME' } }
});
const result = await execute({
schema,
document: gql`
query {
me {
id
username
}
}
`,
contextValue: await context({}),
});
expect(result.errors).toBeFalsy();
expect(result.data['me']['id']).toBe('ID');
expect(result.data['me']['username']).toBe('USERNAME');
});
it('FieldResolver of Query: userById', async () => {
const { schema, context } = new GraphQLModule({
imports: [UserModule],
resolvers: UserModule.resolvers,
providers: [
{
provide: UserProvider,
overwrite: true,
useValue: {
userById: (id: string) => { id, username: 'NAME' }
}
}
]
UserModule.injector.provide({
provide: UserProvider,
overwrite: true,
useValue: {
userById: (id: string) => { id, username: 'USERNAME' }
}
});
const result = await execute({
schema,
Expand Down
24 changes: 21 additions & 3 deletions packages/di/src/injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export class Injector {

if (isTypeProvider(provider)) {
const options: ProviderOptions = Reflect.getMetadata(PROVIDER_OPTIONS, provider);
if (options && !options.overwrite && this.has(provider)) {
if (this.has(provider)) {
throw new ProviderAlreadyDefinedError(this._name, provider);
}
this._classMap.set(provider, provider);
Expand All @@ -51,8 +51,26 @@ export class Injector {
return;
}

if (!provider.overwrite && this.has(provider.provide)) {
throw new ProviderAlreadyDefinedError(this._name, provider.provide);
if (this.has(provider.provide)) {
if (!provider.overwrite) {
throw new ProviderAlreadyDefinedError(this._name, provider.provide);
} else {
this._classMap.delete(provider.provide);
this._factoryMap.delete(provider.provide);
this._instanceMap.delete(provider.provide);
this._applicationScopeServiceIdentifiers.splice(
this._applicationScopeServiceIdentifiers.indexOf(provider.provide),
1,
);
this._sessionScopeServiceIdentifiers.splice(
this._applicationScopeServiceIdentifiers.indexOf(provider.provide),
1,
);
this._requestScopeServiceIdentifiers.splice(
this._applicationScopeServiceIdentifiers.indexOf(provider.provide),
1,
);
}
}

if (isValueProvider(provider)) {
Expand Down
25 changes: 24 additions & 1 deletion packages/di/tests/di.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
import 'reflect-metadata';
import { Injectable, Injector } from '../src';

describe('Dependency Injection', async () => {
it('should do something', async () => {});
it('clear instances if provider is overwritten', async () => {
@Injectable()
class FooProvider {
foo() {
return 'FOO';
}
}
const injector = new Injector();
injector.provide(FooProvider);
expect(injector.get(FooProvider).foo()).toBe('FOO');
injector.provide({
provide: FooProvider,
overwrite: true,
useValue: {
foo() {
return 'BAR';
},
},
});
expect(injector.get(FooProvider).foo()).toBe('BAR');
});
});
14 changes: 14 additions & 0 deletions packages/di/tests/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"module": "commonjs",
"target": "es2018",
"lib": [
"es2018",
"esnext.asynciterable"
],
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"outDir": "../dist/tests",
}
}

0 comments on commit ec07aed

Please sign in to comment.