正在显示
1 个修改的文件
包含
68 行增加
和
13 行删除
| @@ -4,15 +4,19 @@ import com.google.protobuf.util.JsonFormat | @@ -4,15 +4,19 @@ import com.google.protobuf.util.JsonFormat | ||
| 4 | import io.livekit.android.util.toOkioByteString | 4 | import io.livekit.android.util.toOkioByteString |
| 5 | import kotlinx.coroutines.ExperimentalCoroutinesApi | 5 | import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 6 | import kotlinx.coroutines.async | 6 | import kotlinx.coroutines.async |
| 7 | +import kotlinx.coroutines.test.TestCoroutineDispatcher | ||
| 7 | import kotlinx.coroutines.test.TestCoroutineScope | 8 | import kotlinx.coroutines.test.TestCoroutineScope |
| 8 | import kotlinx.coroutines.test.runBlockingTest | 9 | import kotlinx.coroutines.test.runBlockingTest |
| 9 | import kotlinx.serialization.json.Json | 10 | import kotlinx.serialization.json.Json |
| 10 | import livekit.LivekitRtc | 11 | import livekit.LivekitRtc |
| 11 | import okhttp3.* | 12 | import okhttp3.* |
| 13 | +import org.junit.After | ||
| 12 | import org.junit.Assert | 14 | import org.junit.Assert |
| 13 | import org.junit.Before | 15 | import org.junit.Before |
| 14 | import org.junit.Test | 16 | import org.junit.Test |
| 15 | import org.mockito.Mockito | 17 | import org.mockito.Mockito |
| 18 | +import org.mockito.kotlin.argThat | ||
| 19 | +import org.webrtc.SessionDescription | ||
| 16 | 20 | ||
| 17 | @ExperimentalCoroutinesApi | 21 | @ExperimentalCoroutinesApi |
| 18 | class SignalClientTest { | 22 | class SignalClientTest { |
| @@ -22,6 +26,9 @@ class SignalClientTest { | @@ -22,6 +26,9 @@ class SignalClientTest { | ||
| 22 | lateinit var listener: SignalClient.Listener | 26 | lateinit var listener: SignalClient.Listener |
| 23 | lateinit var okHttpClient: OkHttpClient | 27 | lateinit var okHttpClient: OkHttpClient |
| 24 | 28 | ||
| 29 | + lateinit var coroutineDispatcher: TestCoroutineDispatcher | ||
| 30 | + lateinit var coroutineScope: TestCoroutineScope | ||
| 31 | + | ||
| 25 | class MockWebsocketFactory : WebSocket.Factory { | 32 | class MockWebsocketFactory : WebSocket.Factory { |
| 26 | lateinit var ws: WebSocket | 33 | lateinit var ws: WebSocket |
| 27 | lateinit var request: Request | 34 | lateinit var request: Request |
| @@ -34,6 +41,8 @@ class SignalClientTest { | @@ -34,6 +41,8 @@ class SignalClientTest { | ||
| 34 | 41 | ||
| 35 | @Before | 42 | @Before |
| 36 | fun setup() { | 43 | fun setup() { |
| 44 | + coroutineDispatcher = TestCoroutineDispatcher() | ||
| 45 | + coroutineScope = TestCoroutineScope(coroutineDispatcher) | ||
| 37 | wsFactory = MockWebsocketFactory() | 46 | wsFactory = MockWebsocketFactory() |
| 38 | okHttpClient = Mockito.mock(OkHttpClient::class.java) | 47 | okHttpClient = Mockito.mock(OkHttpClient::class.java) |
| 39 | client = SignalClient( | 48 | client = SignalClient( |
| @@ -43,11 +52,17 @@ class SignalClientTest { | @@ -43,11 +52,17 @@ class SignalClientTest { | ||
| 43 | Json, | 52 | Json, |
| 44 | useJson = false, | 53 | useJson = false, |
| 45 | okHttpClient = okHttpClient, | 54 | okHttpClient = okHttpClient, |
| 55 | + ioDispatcher = coroutineDispatcher | ||
| 46 | ) | 56 | ) |
| 47 | listener = Mockito.mock(SignalClient.Listener::class.java) | 57 | listener = Mockito.mock(SignalClient.Listener::class.java) |
| 48 | client.listener = listener | 58 | client.listener = listener |
| 49 | } | 59 | } |
| 50 | 60 | ||
| 61 | + @After | ||
| 62 | + fun tearDown() { | ||
| 63 | + coroutineScope.cleanupTestCoroutines() | ||
| 64 | + } | ||
| 65 | + | ||
| 51 | private fun createOpenResponse(request: Request): Response { | 66 | private fun createOpenResponse(request: Request): Response { |
| 52 | return Response.Builder() | 67 | return Response.Builder() |
| 53 | .request(request) | 68 | .request(request) |
| @@ -59,13 +74,11 @@ class SignalClientTest { | @@ -59,13 +74,11 @@ class SignalClientTest { | ||
| 59 | 74 | ||
| 60 | @Test | 75 | @Test |
| 61 | fun joinAndResponse() { | 76 | fun joinAndResponse() { |
| 62 | - val job = TestCoroutineScope().async { | ||
| 63 | - client.join("http://www.example.com", "", null) | 77 | + val job = coroutineScope.async { |
| 78 | + client.join(EXAMPLE_URL, "", null) | ||
| 64 | } | 79 | } |
| 65 | - client.onOpen( | ||
| 66 | - wsFactory.ws, | ||
| 67 | - createOpenResponse(wsFactory.request) | ||
| 68 | - ) | 80 | + |
| 81 | + client.onOpen(wsFactory.ws, createOpenResponse(wsFactory.request)) | ||
| 69 | client.onMessage(wsFactory.ws, JOIN.toOkioByteString()) | 82 | client.onMessage(wsFactory.ws, JOIN.toOkioByteString()) |
| 70 | 83 | ||
| 71 | runBlockingTest { | 84 | runBlockingTest { |
| @@ -76,21 +89,55 @@ class SignalClientTest { | @@ -76,21 +89,55 @@ class SignalClientTest { | ||
| 76 | 89 | ||
| 77 | @Test | 90 | @Test |
| 78 | fun reconnect() { | 91 | fun reconnect() { |
| 79 | - val job = TestCoroutineScope().async { | ||
| 80 | - client.reconnect("http://www.example.com", "") | 92 | + val job = coroutineScope.async { |
| 93 | + client.reconnect(EXAMPLE_URL, "") | ||
| 81 | } | 94 | } |
| 82 | - client.onOpen( | ||
| 83 | - wsFactory.ws, | ||
| 84 | - createOpenResponse(wsFactory.request) | ||
| 85 | - ) | 95 | + |
| 96 | + client.onOpen(wsFactory.ws, createOpenResponse(wsFactory.request)) | ||
| 97 | + | ||
| 86 | runBlockingTest { | 98 | runBlockingTest { |
| 87 | job.await() | 99 | job.await() |
| 88 | } | 100 | } |
| 89 | } | 101 | } |
| 90 | 102 | ||
| 103 | + @Test | ||
| 104 | + fun listenerNotCalledUntilOnReady() { | ||
| 105 | + val listener = Mockito.mock(SignalClient.Listener::class.java) | ||
| 106 | + client.listener = listener | ||
| 107 | + | ||
| 108 | + val job = coroutineScope.async { | ||
| 109 | + client.join(EXAMPLE_URL, "", null) | ||
| 110 | + } | ||
| 111 | + client.onOpen(wsFactory.ws, createOpenResponse(wsFactory.request)) | ||
| 112 | + client.onMessage(wsFactory.ws, JOIN.toOkioByteString()) | ||
| 113 | + client.onMessage(wsFactory.ws, OFFER.toOkioByteString()) | ||
| 114 | + | ||
| 115 | + runBlockingTest { job.await() } | ||
| 116 | + | ||
| 117 | + Mockito.verifyNoInteractions(listener) | ||
| 118 | + } | ||
| 119 | + | ||
| 120 | + @Test | ||
| 121 | + fun listenerCalledAfterOnReady() { | ||
| 122 | + val listener = Mockito.mock(SignalClient.Listener::class.java) | ||
| 123 | + client.listener = listener | ||
| 124 | + | ||
| 125 | + val job = coroutineScope.async { | ||
| 126 | + client.join(EXAMPLE_URL, "", null) | ||
| 127 | + } | ||
| 128 | + client.onOpen(wsFactory.ws, createOpenResponse(wsFactory.request)) | ||
| 129 | + client.onMessage(wsFactory.ws, JOIN.toOkioByteString()) | ||
| 130 | + client.onMessage(wsFactory.ws, OFFER.toOkioByteString()) | ||
| 131 | + | ||
| 132 | + runBlockingTest { job.await() } | ||
| 133 | + client.onReady() | ||
| 134 | + Mockito.verify(listener) | ||
| 135 | + .onOffer(argThat { type == SessionDescription.Type.OFFER && description == OFFER.offer.sdp }) | ||
| 136 | + } | ||
| 137 | + | ||
| 91 | // mock data | 138 | // mock data |
| 92 | companion object { | 139 | companion object { |
| 93 | - private val EXAMPLE_URL = "http://www.example.com" | 140 | + private const val EXAMPLE_URL = "http://www.example.com" |
| 94 | 141 | ||
| 95 | private val JOIN = with(LivekitRtc.SignalResponse.newBuilder()) { | 142 | private val JOIN = with(LivekitRtc.SignalResponse.newBuilder()) { |
| 96 | join = with(joinBuilder) { | 143 | join = with(joinBuilder) { |
| @@ -103,5 +150,13 @@ class SignalClientTest { | @@ -103,5 +150,13 @@ class SignalClientTest { | ||
| 103 | } | 150 | } |
| 104 | build() | 151 | build() |
| 105 | } | 152 | } |
| 153 | + private val OFFER = with(LivekitRtc.SignalResponse.newBuilder()) { | ||
| 154 | + offer = with(offerBuilder) { | ||
| 155 | + sdp = "" | ||
| 156 | + type = "offer" | ||
| 157 | + build() | ||
| 158 | + } | ||
| 159 | + build() | ||
| 160 | + } | ||
| 106 | } | 161 | } |
| 107 | } | 162 | } |
-
请 注册 或 登录 后发表评论