簡體   English   中英

Angular 單元測試 - 如何測試創建 Websocket 的服務

[英]Angular Unit Testing - How to test a service which creates a Websocket

我需要為以下代碼編寫單元測試:

getSomething(id: string): Observable<State | null> {
  return new WebSocketSubject(webSocket(`ws://<websocket>`)
    .pipe(
      catchError(err => {
        console.error('Error in WebSocket connection: ', err);
        return concat(
          of(null),
          throwError(err)
        );
      }),
      retryWhen(errors =>
        errors.pipe(
          delay(1000)
        )
      )
    )
  );
}

我想寫兩個測試:

  • 檢查是否創建了 websocket;
  • 在 websocket 連接中生成錯誤以實現良好的覆蓋。

我寫了第一個測試如下,但我不知道這里會發生什么:

it('should get Something create websocket', () => {
  service.getSomething('test').subscribe(
    data => expect(data).toBeInstanceOf(webSocket),
      fail
  ); 
});  

歡迎您的意見。 謝謝。

很難提供一個例子作為評論,所以,這里有完整的答案。

這就是我所說的:

@Injectable()
class WebSocketFactory {
  createWebSocket<T>(url: string): WebSocketSubject<T> {
    return webSocket(url);
  }
}

class SomeClass {
  constructor(private readonly factory: WebSocketFactory) {
  }

  getSomething(id: string): Observable<State | null> {
    return this.factory.createWebSocket(`ws://<websocket>`).pipe(
      catchError((err) => {
        console.error("Error in WebSocket connection: ", err);
        return concat(of(null), throwError(err));
      }),
      retryWhen((errors) => errors.pipe(delay(1000)))
    );
  }
}

如您所見,我已將 websocket 創建抽象為一個微型服務WebSocketFactory ,這為我們帶來了以下好處(注意:這不是一個隨時可以重用的代碼,請閱讀下文):

describe('SomeClass', () => {
  let subject = new Subject<any>();
  let service: SomeClass;

  beforeEach(() => {
    service = new SomeClass({
      createWebSocket: <T>() => subject as WebSocketSubject<T>,
    });
  });

  it('should do something useful', () => {
    subject.next(/* something */);
    service.getSomething('test').subscribe(
      data => expect(data).toBeEqual(/* something */),
        fail
    ); 
  });  
});

如您所見,現在您可以完全控制臨時 websocket 創建的時間和方式,您可以訪問內部結構,您可以發送任何值,提前關閉它等等——只需使用subject ,而不是真正的WebSocket對象。

現在,有一些注釋、警告和提示。

  1. 上面的測試代碼不起作用,它只是說明了這一點。 為了使其工作,您需要實際設置 observable 測試,由於 observable 的異步性質,這相當重要。 這是一個很大的話題,我會從一些像這樣這樣的文章開始。

  2. 我正在使用一個臨時模擬的東西(通過包裝subject實現 WebSocketFactory 的對象文字),但有些東西使這更容易和更強大: spies 但這本身就是一個很大的話題。

  3. 上面的例子很簡單,但如果你的代碼復雜得多,你可能想要使用TestBed提供的TestBed ( docs ) 類並進行提供者覆蓋,而不是手動創建實例。

  4. 顯然webSocket返回WebSocketSubject ( docs ),因此,我相應地調整了代碼。

  5. 除了提供完整的類作為工廠之外,您還可以只使用一個函數(類似於constructor(private readonly webSocket: typeof webSocket) {} ,甚至是constructor(@Optional() private readonly webSocket: typeof webSocket = webSocket) {} ),我只是一般喜歡來包裝類的東西更容易擴展,如果將來的某個任務,要求它。

  6. 我知道這不是一個完整的答案,因為它沒有直接解決您的“我不知道這里會發生什么”——那是因為您遇到了相當復雜的一組混合在一起的主題:依賴倒置——通過抽象來簡化websocket 創建、rxjx/observable 測試(甚至一般的異步操作測試)、單元與功能/集成測試。 這些主題中的每一個都相當龐大,但我希望上面的所有鏈接都能幫助您入門。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM