Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Access] Implement web socket connection mock for unit testing of web socket controller #6635

Closed
Tracked by #6163
Guitarheroua opened this issue Nov 12, 2024 · 2 comments · Fixed by #6762
Closed
Tracked by #6163
Assignees
Labels

Comments

@Guitarheroua
Copy link
Contributor

Guitarheroua commented Nov 12, 2024

No description provided.

@illia-malachyn
Copy link
Contributor

illia-malachyn commented Nov 12, 2024

The WebsocketController accepts a WebSocket connection as an argument. To effectively unit test this, we need to mock the WebSocket connection. However, the Gorilla WebSocket library's connection interface is extensive and challenging to mock directly. To simplify testing, we can create a wrapper interface around the Gorilla WebSocket connection. This wrapper will be easier to mock, allowing us to simulate the WebSocket's behavior with custom channels that facilitate reading and writing data.

The wrapper interface, WebsocketConnection, defines the core methods for testing: ReadJSON, WriteJSON, and Close. Using this interface, we can verify that our controller sends and receives the expected data and behaves as intended.

The code outline below shows how this can be implemented:

type WebsocketConnection interface {
    ReadJSON(v interface{}) error
    WriteJSON(v interface{}) error
    Close() error
}

type GorillaWebsocketConnection struct {
    conn *websocket.Conn
}

func NewGorillaWebsocketConnection(conn *websocket.Conn) *GorillaWebsocketConnection {
    return &GorillaWebsocketConnection{
        conn: conn,
    }
}

// Ensures that GorillaWebsocketConnection satisfies the WebsocketConnection interface
var _ WebsocketConnection = (*GorillaWebsocketConnection)(nil)

In our test setup, a handler can initialize a new WebSocket connection using NewGorillaWebsocketConnection and pass it to the controller:

newConn := NewGorillaWebsocketConnection(conn)
controller := NewWebSocketController(logger, h.websocketConfig, h.streamApi, h.streamConfig, newConn)
controller.HandleConnection(context.TODO())

To facilitate testing, a mock struct, WebsocketConnectionMock, is defined. This mock struct includes custom channels (e.g., socket and testSocket) for simulating the connection behavior, as well as a closed state to indicate if the connection has been terminated.

type WebsocketConnectionMock struct {
    mock.Mock
    socket     chan interface{}
    closed     bool
}

By using this setup, we can easily simulate data exchange through the mock channels and test that WebsocketController performs as expected.

@illia-malachyn
Copy link
Contributor

This should be a P0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants