简体   繁体   中英

In SignalR, is it possible to simulate a reconnect for testing?

I understand that SignalR continually attempts to reconnect if a connection fails for any reason. What's the best way to test my server and client's response to this?

In order for the Client to try to reconnect, you need to configure the HubConnectionBuilder with the withAutomaticReconnect method. The JavaScript code looks something like this:

const connection = new signalR.HubConnectionBuilder()
  .withUrl(`${apiUrl}/subscribe/change`)
  .withAutomaticReconnect()
  .build();

Once that is set, the client will try to reconnect when the connection is lost.

Internally, when SignalR is disconnecting, it calls the stopInternal function.

If you want to do some manual testing to make sure that your handlers are being fired and they do what you expect them to do. You can save the connection in a const and fire the events yourself.

What I did:

  1. Created the connection like in the code above,
  2. Cached the connection in the window object.
    window.signalR = connection;
  1. Opened the browser console, clicked the three dots on the left and navigated to Network conditions .

在此处输入图片说明

  1. Updated Network throttling to offline.

在此处输入图片说明

  1. And finally ran:
signalR.connection.stopInternal();

And my onreconnecting handler started firing. It runs 4 times by default. It looks like this:

connection.onreconnecting(error => {
  console.log('Reconnecting interval', error);
});

NOTE: This strategy is for development and some manual testing only. I wouldn't recommend using the window object for unit tests or integration tests.

A similar strategy can be achieved by caching your connection on some internal variables to be used by unit tests.

To test disconnecting on the server: browse to another page.

To test disconnecting on the client: reset the server (IISreset?).

I found a solution here: https://stackoverflow.com/a/59916046/2929675

Before the WebSocket connection gets opened, you must execute this script to monkey patch the browsers WebSocket function:

const sockets = [];
const nativeWebSocket = window.WebSocket;
window.WebSocket = function(...args){
  const socket = new nativeWebSocket(...args);
  sockets.push(socket);
  return socket;
};

Now you have access to all WebSocket connections via the sockets array. And when you want to trigger a reconnect, you can call

sockets[0].close();

using the index of the connection you want to close.

When SignalR automatic reconnect is enabled, it will automatically try to open a new connection, and the Reconnecting and Reconnected events get fired.

It's a bit hacky, but it's the best solution I have found so far.

It looks like there is also some progress in the chromium issue to support this in the dev tools: https://bugs.chromium.org/p/chromium/issues/detail?id=423246

Updated berhir's snippet for TypeScript

class MockWebSocket extends WebSocket {
    static sockets: WebSocket[] = [];

    constructor(url: string | URL, protocols?: string | string[]) {
        super(url, protocols);

        MockWebSocket.sockets.push(this);
    }
}
window.WebSocket = MockWebSocket;

to close a socket:

MockWebSocket.sockets[index].close();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM