web-dev-qa-db-ja.com

1つのテストのみでAngular 5のProviderをオーバーライドする方法は?

単体テストファイルの1つで、同じサービスを異なるモックで数回モックする必要があります。

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
             */
        });
    });
});

関数 overrideProvider が存在することがわかりましたが、テストで使用することができませんでした。 「it」で使用しても、プロバイダーは変更されません。この関数が呼び出される例を見つけることができませんでした。適切に使用する方法を説明してもらえますか?または、それを行う別の方法がありますか?

10
hbaltz

サービスがパブリックプロパティとして注入される場合、例:

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

次のようなことができます:

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

  // Your test here...
})

挿入されたサービスがプライベートプロパティに格納されている場合、(component as any).myServiceMockMyService2 = new MockMyService2(...); TSをバイパスします。

きれいではありませんが、動作します。

はどうかと言うと TestBed.overrideProvider、私はそのアプローチに運がなかった(うまくいけばもっといいだろう):

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.
});
5
Filip Voska

angular 6の時点で、overrideProvideruseValueプロパティで動作することに気付きました。

_class MockRequestService1 {
  ...
}

class MockRequestService2 {
  ...
}
_

次に、TestBedのように記述します。

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

そして、プロバイダーをオーバーライドしたいときはいつでも使用するだけです:

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

beforeEach()関数内に配置するか、it()関数に配置します。

参照用に、annynoneがこの問題を満たしている場合。

使ってみた

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

動作していませんでした、まだ元のサービスがテストに挿入されました(_providedIn: root_で)

テストでは、aliastoimportOtherService:を使用しました。

_import { OtherService } from '@core/OtherService'`
_

一方、サービス自体にはimportrelative pathがありました:

_import { OtherService } from '../../../OtherService'
_

testserviceの両方に同じインポートTestBed.overrideProvider()が有効になり始めました。

Env:Angular 7ライブラリ-アプリケーションとjestではありません

1
Felix

これはちょうど私のために働いた(Angular 7.x):

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

ログインサービスはMyCoreModuleの一部ですが、モックプロバイダーでオーバーライドできます。また、useValueを使用している場合は、new yourService()を忘れないでください

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