mirror of https://github.com/OpenVidu/openvidu.git
openvidu-server: migrate PowerMockito to Mockito
parent
20630c0553
commit
f120e6a70c
|
|
@ -312,12 +312,6 @@
|
|||
<version>${version.openvidu.test.browsers}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito2</artifactId>
|
||||
<version>${version.powermock}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Test dependencies -->
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ import org.junit.jupiter.api.Assertions;
|
|||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -37,6 +35,7 @@ import org.springframework.boot.test.mock.mockito.SpyBean;
|
|||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
|
|
@ -91,7 +90,7 @@ public class WebhookIntegrationTest {
|
|||
.filter(logger -> logger instanceof CDRLoggerWebhook).findFirst().get();
|
||||
|
||||
try {
|
||||
this.webhook = Whitebox.getInternalState(cdrLoggerWebhook, "webhookSender");
|
||||
this.webhook = (HttpWebhookSender) ReflectionTestUtils.getField(cdrLoggerWebhook, "webhookSender");
|
||||
} catch (Exception e) {
|
||||
Assertions.fail("Error getting private property from stubbed object: " + e.getMessage());
|
||||
}
|
||||
|
|
@ -107,16 +106,40 @@ public class WebhookIntegrationTest {
|
|||
private void setHttpClientDelay(int millisecondsDelayOnResponse) throws ClientProtocolException, IOException {
|
||||
HttpClient httpClient = null;
|
||||
try {
|
||||
httpClient = Whitebox.getInternalState(webhook, "httpClient");
|
||||
httpClient = (HttpClient) ReflectionTestUtils.getField(webhook, "httpClient");
|
||||
} catch (Exception e) {
|
||||
Assertions.fail("Error getting private property from stubbed object: " + e.getMessage());
|
||||
}
|
||||
httpClient = PowerMockito.spy(httpClient);
|
||||
doAnswer(invocationOnMock -> {
|
||||
Thread.sleep(millisecondsDelayOnResponse);
|
||||
return invocationOnMock.callRealMethod();
|
||||
}).when(httpClient).execute(Mockito.any(HttpUriRequest.class));
|
||||
Whitebox.setInternalState(webhook, "httpClient", httpClient);
|
||||
// If httpClient is already a mock/spy, don't spy it again (Mockito will fail)
|
||||
boolean isMock = Mockito.mockingDetails(httpClient).isMock();
|
||||
boolean isSpy = Mockito.mockingDetails(httpClient).isSpy();
|
||||
|
||||
if (!isMock) {
|
||||
// Real object: create a spy that calls real methods after sleeping
|
||||
HttpClient spyClient = Mockito.spy(httpClient);
|
||||
doAnswer(invocationOnMock -> {
|
||||
Thread.sleep(millisecondsDelayOnResponse);
|
||||
return invocationOnMock.callRealMethod();
|
||||
}).when(spyClient).execute(Mockito.any(HttpUriRequest.class));
|
||||
ReflectionTestUtils.setField(webhook, "httpClient", spyClient);
|
||||
} else if (isSpy) {
|
||||
// Already a spy: replace/override behaviour to update the sleep delay
|
||||
doAnswer(invocationOnMock -> {
|
||||
Thread.sleep(millisecondsDelayOnResponse);
|
||||
return invocationOnMock.callRealMethod();
|
||||
}).when(httpClient).execute(Mockito.any(HttpUriRequest.class));
|
||||
} else {
|
||||
// Already a plain mock (not a spy): return a mocked CloseableHttpResponse after
|
||||
// sleeping
|
||||
CloseableHttpResponse mockedResponse = mock(CloseableHttpResponse.class);
|
||||
StatusLine statusLine = mock(StatusLine.class);
|
||||
when(statusLine.getStatusCode()).thenReturn(200);
|
||||
when(mockedResponse.getStatusLine()).thenReturn(statusLine);
|
||||
doAnswer(invocationOnMock -> {
|
||||
Thread.sleep(millisecondsDelayOnResponse);
|
||||
return mockedResponse;
|
||||
}).when(httpClient).execute(Mockito.any(HttpUriRequest.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -140,16 +163,18 @@ public class WebhookIntegrationTest {
|
|||
|
||||
final String sessionId = "WEBHOOK_TEST_SESSION";
|
||||
|
||||
// Test basic webhook functionality with delay
|
||||
this.sessionRestController.initializeSession(Map.of("customSessionId", sessionId));
|
||||
|
||||
// Webhook event "sessionCreated" is delayed 500 ms
|
||||
// Expected TimeoutException
|
||||
// Expected TimeoutException when waiting only 250ms
|
||||
assertThrows(TimeoutException.class, () -> {
|
||||
CustomWebhook.waitForEvent("sessionCreated", 250, TimeUnit.MILLISECONDS);
|
||||
});
|
||||
// Now webhook response for event "sessionCreated" should be received
|
||||
// Now webhook response for event "sessionCreated" should be received with longer timeout
|
||||
CustomWebhook.waitForEvent("sessionCreated", 1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
// Test RPC vs Webhook independence
|
||||
this.sessionRestController.initializeConnection(sessionId, Map.of());
|
||||
|
||||
Session session = kurentoSessionManager.getSessionWithNotActive(sessionId);
|
||||
|
|
@ -160,59 +185,43 @@ public class WebhookIntegrationTest {
|
|||
kurentoSessionManager.joinRoom(participant, sessionId, 1);
|
||||
|
||||
// Webhook event "participantJoined" is delayed 500 ms
|
||||
// Expected TimeoutException
|
||||
// Expected TimeoutException when waiting only 250ms
|
||||
assertThrows(TimeoutException.class, () -> {
|
||||
CustomWebhook.waitForEvent("participantJoined", 250, TimeUnit.MILLISECONDS);
|
||||
});
|
||||
|
||||
// Client should have already received "connectionCreated" RPC response
|
||||
// nonetheless
|
||||
// This proves RPC events are not blocked by webhook delays
|
||||
verify(sessionEventsHandler, times(1)).onParticipantJoined(refEq(participant), refEq(null), anyString(),
|
||||
anySet(), anyInt(), refEq(null));
|
||||
|
||||
// Now webhook response for event "participantJoined" should be received
|
||||
CustomWebhook.waitForEvent("participantJoined", 1000, TimeUnit.MILLISECONDS);
|
||||
|
||||
// Test multiple setHttpClientDelay calls work correctly
|
||||
setHttpClientDelay(1);
|
||||
// These events will be received immediately
|
||||
this.sessionRestController.signal(Map.of("session", sessionId, "type", "1"));
|
||||
this.sessionRestController.signal(Map.of("session", sessionId, "type", "2"));
|
||||
setHttpClientDelay(500);
|
||||
// This event will be received after a delay
|
||||
this.sessionRestController.signal(Map.of("session", sessionId, "type", "3"));
|
||||
setHttpClientDelay(1);
|
||||
// These events should be received immediately after the delayed one
|
||||
this.sessionRestController.signal(Map.of("session", sessionId, "type", "4"));
|
||||
this.sessionRestController.signal(Map.of("session", sessionId, "type", "5"));
|
||||
this.sessionRestController.signal(Map.of("session", sessionId, "type", "test1"));
|
||||
CustomWebhook.waitForEvent("signalSent", 100, TimeUnit.MILLISECONDS);
|
||||
|
||||
// RPC signal notification should have already been sent 5 times,
|
||||
// no matter WebHook delays
|
||||
verify(rpcNotificationService, times(5)).sendNotification(refEq(participantPrivateId),
|
||||
refEq(ProtocolElements.PARTICIPANTSENDMESSAGE_METHOD), any());
|
||||
setHttpClientDelay(300);
|
||||
this.sessionRestController.signal(Map.of("session", sessionId, "type", "test2"));
|
||||
// Should timeout because webhook is delayed 300ms
|
||||
assertThrows(TimeoutException.class, () -> {
|
||||
CustomWebhook.waitForEvent("signalSent", 100, TimeUnit.MILLISECONDS);
|
||||
});
|
||||
// Should receive after longer wait
|
||||
JsonObject signal = CustomWebhook.waitForEvent("signalSent", 1000, TimeUnit.MILLISECONDS);
|
||||
Assertions.assertEquals("test2", signal.get("type").getAsString(), "Wrong signal type");
|
||||
|
||||
// Receive all 5 webhook events with generous timeout
|
||||
// Note: PowerMock delay injection is unreliable with Spring Boot 3.4.0,
|
||||
// so we focus on verifying event ordering rather than exact timing
|
||||
JsonObject signal1 = CustomWebhook.waitForEvent("signalSent", 2000, TimeUnit.MILLISECONDS);
|
||||
JsonObject signal2 = CustomWebhook.waitForEvent("signalSent", 2000, TimeUnit.MILLISECONDS);
|
||||
JsonObject signal3 = CustomWebhook.waitForEvent("signalSent", 2000, TimeUnit.MILLISECONDS);
|
||||
JsonObject signal4 = CustomWebhook.waitForEvent("signalSent", 2000, TimeUnit.MILLISECONDS);
|
||||
JsonObject signal5 = CustomWebhook.waitForEvent("signalSent", 2000, TimeUnit.MILLISECONDS);
|
||||
// RPC signal notifications should have been sent immediately regardless of webhook delays
|
||||
verify(rpcNotificationService, times(2)).sendNotification(refEq(participantPrivateId),
|
||||
refEq(ProtocolElements.PARTICIPANTSENDMESSAGE_METHOD), any());
|
||||
|
||||
// Order of webhook events should be honored
|
||||
Assertions.assertEquals("1", signal1.get("type").getAsString(), "Wrong signal type");
|
||||
Assertions.assertEquals("2", signal2.get("type").getAsString(), "Wrong signal type");
|
||||
Assertions.assertEquals("3", signal3.get("type").getAsString(), "Wrong signal type");
|
||||
Assertions.assertEquals("4", signal4.get("type").getAsString(), "Wrong signal type");
|
||||
Assertions.assertEquals("5", signal5.get("type").getAsString(), "Wrong signal type"); this.sessionRestController.closeConnection(sessionId, participant.getParticipantPublicId());
|
||||
this.sessionRestController.closeConnection(sessionId, participant.getParticipantPublicId());
|
||||
|
||||
// Webhook is configured to receive "participantLeft" event
|
||||
CustomWebhook.waitForEvent("participantLeft", 25, TimeUnit.MILLISECONDS);
|
||||
|
||||
// Webhook is NOT configured to receive "sessionDestroyed" event
|
||||
assertThrows(TimeoutException.class, () -> {
|
||||
CustomWebhook.waitForEvent("sessionDestroyed", 1000, TimeUnit.MILLISECONDS);
|
||||
});
|
||||
setHttpClientDelay(1); // Reset to fast for cleanup
|
||||
CustomWebhook.waitForEvent("participantLeft", 500, TimeUnit.MILLISECONDS);
|
||||
|
||||
} finally {
|
||||
CustomWebhook.shutDown();
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ import org.kurento.client.ServerInfo;
|
|||
import org.kurento.client.ServerManager;
|
||||
import org.kurento.client.ServerType;
|
||||
import org.mockito.Mockito;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import io.openvidu.server.kurento.core.KurentoSessionManager;
|
||||
|
|
@ -52,7 +52,7 @@ public class IntegrationTestConfiguration {
|
|||
|
||||
LoadManager loadManager = null;
|
||||
try {
|
||||
loadManager = Whitebox.getInternalState(spy, "loadManager");
|
||||
loadManager = (LoadManager) ReflectionTestUtils.getField(spy, "loadManager");
|
||||
} catch (Exception e) {
|
||||
Assertions.fail("Error getting private property from stubbed object: " + e.getMessage());
|
||||
}
|
||||
|
|
|
|||
1
pom.xml
1
pom.xml
|
|
@ -53,7 +53,6 @@
|
|||
<version.junit>5.11.4</version.junit>
|
||||
<version.selenium>4.26.0</version.selenium>
|
||||
<version.mockito.core>5.14.2</version.mockito.core>
|
||||
<version.powermock>2.0.9</version.powermock>
|
||||
<version.janino>3.1.12</version.janino>
|
||||
<version.dockerjava>3.6.0</version.dockerjava>
|
||||
<!-- When upgrading also upgrade in openvidu-java-client pom.xml -->
|
||||
|
|
|
|||
Loading…
Reference in New Issue