wake-up-neo.net

Wie überschreibe ich Provider in Angular 5 für nur einen Test?

In einer meiner Unit-Test-Dateien muss ich den gleichen Dienst mehrmals mit verschiedenen Mocks verspotten.

import { MyService } from '../services/myservice.service';
import { MockMyService1 } from '../mocks/mockmyservice1';
import { MockMyService2 } from '../mocks/mockmyservice2';
describe('MyComponent', () => {

    beforeEach(async(() => {
        TestBed.configureTestingModule({
        declarations: [
            MyComponent
        ],
        providers: [
            { provide: MyService, useClass: MockMyService1 }
        ]
        })
        .compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(MapComponent);
        mapComponent = fixture.componentInstance;
        fixture.detectChanges();
    });

    describe('MyFirstTest', () => {
        it('should test with my first mock', () => {
            /**
             * Test with my first mock
             */
        });
    });

    describe('MySecondTest', () => {
        // Here I would like to change { provide: MyService, useClass: MockMyService1 } to { provide: MyService, useClass: MockMyService2 }

        it('should test with my second mock', () => {
            /**
             * Test with my second mock
             */
        });
    });
});

Ich sehe, dass die Funktion overrideProvider existiert, aber ich habe es nicht geschafft, sie in meinem Test zu verwenden. Wenn ich es in einem "es" verwende, ändert sich der Anbieter nicht. Es ist mir nicht gelungen, ein Beispiel zu finden, in dem diese Funktion aufgerufen wird. Können Sie mir erklären, wie ich es richtig benutze? Oder haben Sie eine andere Methode, um das zu tun?

4
hbaltz

Wenn der Dienst als öffentliches Eigentum injiziert wird, z.

@Component(...)
class MyComponent {
  constructor(public myService: MyService)
}

Sie können so etwas tun:

it('...', () => {
  component.myService = new MockMyService2(...); // Make sure to provide MockMyService2 dependencies in constructor, if it has any.
  fixture.detectChanges();

  // Your test here...
})

Wenn der injizierte Dienst in einer privaten Eigenschaft gespeichert ist, können Sie ihn als (component as any).myServiceMockMyService2 = new MockMyService2(...); schreiben, um den TS zu umgehen.

Es ist nicht schön, aber es funktioniert.

Was TestBed.overrideProvider anbelangt, hatte ich mit diesem Ansatz kein Glück (was viel schöner wäre, wenn es funktioniert):

it('...', () =>{
  TestBed.overrideProvider(MyService, { useClass: MockMyService2 });
  TestBed.compileComponents();
  fixture = TestBed.createComponent(ConfirmationModalComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();

  // This was still using the original service, not sure what is wrong here.
});
1
Filip Voska

Seit dem Winkel von 6 ist mir aufgefallen, dass overrideProvider mit der useValue-Eigenschaft arbeitet. Um es zum Laufen zu bringen, probieren Sie so etwas wie:

class MockRequestService1 {
  ...
}

class MockRequestService2 {
  ...
}

dann schreibe dir TestBed wie:

// example with injected service
TestBed.configureTestingModule({
  // Provide the service-under-test
  providers: [
    SomeService, {
      provide: SomeInjectedService, useValue: {}
    }
  ]
});

Und wann immer Sie den Provider überschreiben möchten, verwenden Sie einfach:

TestBed.overrideProvider(SomeInjectedService, {useValue: new MockRequestService1()});
// Inject both the service-to-test and its (spy) dependency
someService = TestBed.get(SomeService);
someInjectedService = TestBed.get(SomeInjectedService);

Entweder in einer beforeEach()-Funktion oder in einer it()-Funktion.

Nur als Referenz, wenn Annynone dieses Problem erfüllt.

Ich habe versucht zu verwenden

TestBed.overrideProvider(MockedService, {useValue: { foo: () => {} } });

es hat nicht funktioniert, im Test wurde noch der ursprüngliche Service eingespritzt (der mit providedIn: root)

Im Test habe ich Alias ​​ verwendet, um OtherService zu importieren :

import { OtherService } from '@core/OtherService'`

während im Dienst selbst hatte ich Import mit relativen Pfad :

import { OtherService } from '../../../OtherService'

Nach der Korrektur hatten sich also sowohl Test als auch Service gleiche ImporteTestBed.overrideProvider() wurde wirksam.

Env: Angular 7 library - nicht application und jest

1
Felix

Das hat gerade für mich funktioniert (Angular 7.x):

 imports: [ MyCoreModule.forRoot()],
 providers: [{provide: LoginService, useValue: new LoginServiceMock()}]

Der Anmeldedienst ist Teil des MyCoreModule, aber ich kann ihn mit dem Scheinanbieter überschreiben. Wenn Sie useValue verwenden, vergessen Sie nicht das new yourService ().

{ provide: MyService, useValue: new MockMyService1() }
0
David Dehghan