如何在Angular单元测试中建立Websocket连接?

时间:2018-08-27 10:26:07

标签: angular unit-testing websocket

我正在开发一个Angular(v 6.1.0)应用程序,该应用程序通过websocket与后端进行通信。到目前为止,除了单元测试之外,其他所有东西都运行良好。我已经创建了一个模拟后端来测试我的组件,但是我无法在模拟后端和测试模块之间建立连接。我将Jasmine用作断言库,将Jest用作测试运行器,这是一个示例测试套件:

describe('RandomComponent', () => {
  let component: RandomComponent;
  let fixture: ComponentFixture<RandomComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [],
      imports: [SomeModule],
      providers: [SpecialWebSocketService, WebSocketService,
        { provide: BackendUrlService, useClass: BackendUrlMockService }
      ]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(RandomComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create random component', () => {
      expect(component).toBeTruthy();
  });
});

BackendUrlMockService只是用来提供URL。单个测试用例产生以下结果:

 FAIL  src/app/path/to/my/random.component.spec.ts
  RandomComponent
    ✕ should create random component (603ms)

  ● RandomComponent › should create random component

    InvalidStateError: Still in CONNECTING state.

应用程序在真实后端和模拟后端均可正常运行。测试模块都不能使用。我还注意到,如果我向测试用例添加超时:

it('should create random component', (done) => {
  setTimeout(() => {
    expect(component).toBeTruthy();
    done();
  }, 1000);
});

我的模拟后端记录一条消息,指出连接已正确建立,但仍然出现错误。有谁知道如何正确设置所有内容以便测试组件?

1 个答案:

答案 0 :(得分:1)

基于@ user184994的评论,我决定模拟websocket而不是后端:

const mockData = {
  // some arbitrary data
};

class WebSocketServiceSpy {

  private messageSpy = new Subject<string>();
  private messageHandler = this.messageSpy.asObservable();

  createObservableSocket(url: string): Observable<string> {
    console.log(`Websocket would connect to ${url}.`);

   return new Observable(observer => {
      this.messageHandler.subscribe(() => {
        observer.next(JSON.stringify(mockData));
      });
    });
  }

  sendMessage(message: any) {
    this.messageSpy.next();
  }
}

然后,我在测试模块中使用了它:

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [],
    imports: [SomeModule],
      providers: [SpecialWebSocketService, BackendUrlService,
        { provide: WebSocketService, useClass: WebSocketServiceSpy }  
    ]
  })
    .compileComponents();
}));

测试终于变成绿色:

PASS  src/app/path/to/my/random.component.spec.ts
 ● Console

   console.log src/app/path/to/my/random.component.spec.ts:911
     Websocket would connect to <actual url>.