【问题标题】:How do I Mock an Angular 2 route?如何模拟 Angular 2 路线?
【发布时间】:2017-04-12 17:05:07
【问题描述】:

我有以下代码...

export class LoginComponent {
    userName: string;
    password: string;
    rememberMe: boolean = false;
    constructor( private auth: AuthenticationService,
                 private router: Router) {
      ...
    }
    ...
}

我正在尝试进行单元测试,但我的第一次尝试失败了......

beforeEach(() => {
        router = new Router();
        component = new LoginComponent(authService, router);
});

因为它需要路由器构造函数的参数。 Here I saw...

beforeEach(() => addProviders([
    APP_ROUTER_PROVIDERS, // must be first
    {provide: APP_BASE_HREF, useValue: '/'}, // must be second
    {provide: ActivatedRoute, useClass: Mock},
    {provide: Router, useClass: Mock}
]));

但我的依赖项中似乎没有 APP_ROUTER_PROVIDERSMock,所以我认为它可能已经过时(或者我需要依赖项)。

我该如何模拟呢?这对我正在做的测试都没有关系。

【问题讨论】:

    标签: angular karma-jasmine angular2-routing angular2-testing angular2-router3


    【解决方案1】:

    对于一个简单的情况,您可以创建自己的模拟并按值提供,例如:

    describe('whatever', () => {
      let mockRouter: any;
      ...
    
      beforeEach(async(() => {
        // create your own mock 
        mockRouter = jasmine.createSpyObj('Router', ['navigate']);
    
        ...
    
        TestBed.configureTestingModule({
          declarations: [LoginComponent],
          providers: [
            // provide it by value
            { provide: Router, useValue: mockRouter },
            ...
          ],
        }).compileComponents();
      }));
    
      ...
    
    }); 
    

    这使用了测试台的依赖注入,而不是尝试“new-up”被测类。

    有关上下文的示例,请参见例如one of my projects on GitHub

    【讨论】:

    • 这与实际项目的执行方式有何不同(我在查看之前已发布)。看来我们只需要...TestBed.configureTestingModule({imports: [RouterTestingModule]});router = TestBed.get(Router);?不过我还没有测试过,所以我不确定它是否有效。
    • @Jackie 你是什么意思“实际项目”
    • @Jackie 他们正在测试路由器本身,您正在测试使用它的东西。您看过我链接的示例并尝试过吗?
    • 我会试着多看一点,看看能不能明白。抱歉,这些东西对我来说似乎很深奥。就我而言,我不关心副作用 LOL,但我认为你所说的是这会做一些我不需要的额外东西。
    【解决方案2】:

    这是为每个测试加载查询字符串参数的工作示例。适用于 Angular 2.3。

      beforeEach(async(() => {
        TestBed.configureTestingModule({
          declarations: [
            MyViewerComponent,
            ...
          ],
          imports: [
            HttpModule,
            FormsModule,
            RouterModule,
            ...  
          ],
          providers: [
            {provide: ActivatedRoute, useValue: {queryParams: {test: 111}}},
            {provide: MyService, useClass: MyMockService}
          ]
        })
          .compileComponents();
      }));
    

    【讨论】:

      【解决方案3】:

      我接受了上面的答案,因为它似乎是正确的,但是,我实际上以不同的方式实现它......

      describe("Login Component", () => {
          let component: LoginComponent;
          let authService: AuthenticationService;
          let router: Router;
      
          describe("Testing the subscription happens", () => {
              beforeEach(() => {
                  TestBed.configureTestingModule({imports: [RouterTestingModule]});
                  router = TestBed.get(Router);
                  authService = new AuthenticationService();
                  authService.notifications = new Subject();
                  authService.notifications.subscribe = jasmine.createSpy("SpyToTestNotifications");
              });
              it("Make sure we try to subscribe to the auth event", () => {
                  component = new LoginComponent(authService, router);
                  expect(authService.notifications.subscribe).toHaveBeenCalled();
              })
          });
      });
      

      如您所见,这仅需要 beforeEach 中的 2 行...

      TestBed.configureTestingModule({imports: [RouterTestingModule]});
      router = TestBed.get(Router);
      

      但是,根据@jonrsharpe,这会做很多事情,因此您无法保证可能会发生什么其他副作用。但它很快,它很脏而且它似乎确实“工作”

      【讨论】:

        猜你喜欢
        • 2017-07-28
        • 1970-01-01
        • 2017-10-27
        • 2023-04-04
        • 1970-01-01
        • 2022-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多