使用 Mockk 模拟 SocketIO 的发射功能

Mocking emit function of SocketIO with Mockk

目前我正在尝试模拟 socket.emit 方法的回调,该方法包装在 SocketIO 的 Ack class 中。

我发送特定事件的函数如下所示:

fun send(info: info): Completable {
    return Completable.create { emitter ->
        _socket.emit("info", info.mapRepresentation, Ack() {
            fun call(vararg args: Any?) {
                emitter.onComplete()
            }
        })
    }
}

确认 class socketIO:

package io.socket.client;

/**
 * Acknowledgement.
 */
public interface Ack {

    public void call(Object... args);

}

现在我想模拟 socket.emit 方法,以便在每次 socket.emit 调用时调用 Ack.call 方法:

@Test
fun sendInfo_socketConfigured_infoSent() {
    val info = info(123, "x", "x")
    testSubject.send(info).test().assertComplete()
    every {
        socket.emit("info", info.mapRepresentation, any())
    } answers {
        thirdArg<Ack>.call()
    }
}

问题是,我不知道如何使用 Mockk 准确调用此 Ack.call 方法,因为 Mockk 需要在答案块中有一个发射器,但我提供了一个单元。我什至用我的方法来测试方法 testSubject.send()?

我正在使用 'io.socket:socket.io-client:1.0.0'

有一个原则说你不应该再追求这个:Don't mock what you don't


要解决这些情况,最好围绕难以集成的部分创建包装器。此技术允许您在测试场景中为其创建模拟或存根。使用包装器,您可以将该包装器的一个实例传递给 testSubject,它在 send 中使用它。在对域和上下文了解不多的情况下,只是为了给您一个想法,类似以下内容可能会有所帮助:

interface SocketEmitter(){
   fun emit(socket: Socket, event: ...) // maybe socket can even go into constructor list to make it a field
} 

//default implementation
class DefaultSocketEmitter(): SocketEmitter {
   override fun emit(...) = socket.emit(...)
}

//in your test you would pass a stub or mock if verification is needed (which isn't most of the time)
createTestSubject(object: SocketEmitter { 
    override fun emit(...) = Unit // whatever makes sense
})