baldmark
baldmark

Reputation: 707

"No provider for String" in service test

I have a problem illustrated at http://plnkr.co/edit/ctjo8s8iUBPL9yUaVxP5?p=preview (adapted from the working example at http://plnkr.co/edit/N3Acjuk7g9sPs35Rchjg?p=preview by making small changes to src/langaugesService.ts). I added the constructor.

export class LanguagesService {
  private type: string;
  constructor(type: string) {
    this.type = type;
  }
  get() {
    return ['en', 'es', 'fr'];
  }
}

What do I ned to do to fix the test below (from src/languagesService.spec.ts)?

import {describe, it, expect, inject, beforeEach, beforeEachProviders} from 'angular2/testing';
import {LanguagesService} from './languagesService';

describe('Service: LanguagesService', () => {
  let service;

  beforeEachProviders(() => [
    LanguagesService
  ]);

  beforeEach(inject([LanguagesService], s => {
    service = s;
  }));

  it('should return available languages', () => {
    let languages = service.get();
    expect(languages).toContain('en');
    expect(languages).toContain('es');
    expect(languages).toContain('fr');
    expect(languages.length).toEqual(3);
  });
}) 

Upvotes: 3

Views: 2621

Answers (1)

Günter Zöchbauer
Günter Zöchbauer

Reputation: 657158

When you have constructor parameters for class that are injected by DI there need to be providers registered for these parameters for DI to be able to resolve them.

There is no default provider for string and adding a provider for string won't buy you much because that type is usually not specific enough.

What you could do is to provide a value with a string key (or alternatively OpaqueToken like

@Component({
  selector: 'my-app',
  providers: [/* other providers, */ {provide: 'languageType', useValue: 'someValue'}]
  ...
})

and then your service should look like

@Injectable()
export class LanguagesService {
  private type: string;
  constructor(@Inject('languageType') type: string) {
    this.type = type;
  }
  get() {
    return ['en', 'es', 'fr'];
  }
}

alternatively you can make the argument just optional, then DI passes null when it can't resolve the dependency:

@Injectable()
export class LanguagesService {
  private type: string;
  constructor(@Optional() type: string) {
    this.type = type;
  }
  get() {
    return ['en', 'es', 'fr'];
  }
}

Upvotes: 1

Related Questions