Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save musketyr/1faa312d0438baa7d697babeae6f0355 to your computer and use it in GitHub Desktop.

Select an option

Save musketyr/1faa312d0438baa7d697babeae6f0355 to your computer and use it in GitHub Desktop.
Spock to JUnit 5 Migration Diff - ConnectCallbackControllerSpec (sc185842)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Spock → JUnit 5 Migration: ConnectCallbackControllerSpec</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; padding: 20px; line-height: 1.6; }
h1 { text-align: center; margin-bottom: 20px; color: #333; }
.section { background: white; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); overflow: hidden; }
.section-header { background: #2d3748; color: white; padding: 12px 16px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; }
.section-header:hover { background: #4a5568; }
.section-header h2 { font-size: 16px; font-weight: 600; }
.section-header .toggle { font-size: 12px; }
.section-content { display: block; }
.section-content.collapsed { display: none; }
.diff-container { display: grid; grid-template-columns: 1fr 1fr; }
.diff-panel { padding: 16px; overflow-x: auto; }
.diff-panel.left { background: #fff5f5; border-right: 1px solid #e2e8f0; }
.diff-panel.right { background: #f0fff4; }
.diff-panel h3 { font-size: 12px; text-transform: uppercase; color: #718096; margin-bottom: 12px; letter-spacing: 0.5px; }
pre { font-family: 'SF Mono', Monaco, 'Courier New', monospace; font-size: 13px; white-space: pre-wrap; word-wrap: break-word; }
.left pre { color: #c53030; }
.right pre { color: #276749; }
.summary { background: #c6f6d5; border-left: 4px solid #38a169; padding: 12px 16px; margin: 0; }
.summary p { color: #276749; font-size: 14px; }
.summary strong { color: #22543d; }
@media (max-width: 768px) { .diff-container { grid-template-columns: 1fr; } .diff-panel.left { border-right: none; border-bottom: 1px solid #e2e8f0; } }
</style>
</head>
<body>
<h1>🦀 Spock → JUnit 5 Migration: ConnectCallbackControllerSpec</h1>
<p style="text-align: center; color: #666; margin-bottom: 20px;">Story: <a href="https://app.shortcut.com/agorapulse/story/185842">sc185842</a> | PR: <a href="https://github.com/agorapulse/platform/pull/72757">#72757</a></p>
<!-- Section: Imports -->
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>📦 Imports</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre>package agorapulse.roi.api.connect
import agorapulse.roi.service.google.client.connect.GoogleAnalyticsConnectService
import com.agorapulse.gru.Gru
import io.micronaut.context.annotation.Property
import io.micronaut.test.annotation.MockBean
import io.micronaut.test.extensions.spock.annotation.MicronautTest
import jakarta.inject.Inject
import spock.lang.Specification</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre>package agorapulse.roi.api.connect;
import agorapulse.roi.service.google.client.connect.GoogleAnalyticsConnectService;
import com.agorapulse.gru.Gru;
import io.micronaut.context.annotation.Property;
import io.micronaut.test.annotation.MockBean;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.net.URI;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;</pre>
</div>
</div>
<div class="summary">
<p><strong>Changes:</strong> Replaced Spock imports with JUnit 5 and Mockito. Added @Test, Mockito static imports, and java.net.URI import.</p>
</div>
</div>
</div>
<!-- Section: Class & Fields -->
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🏗️ Class & Fields</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre>@MicronautTest
@Property(name = "mock.jwt.identity.enabled", value = "true")
class ConnectCallbackControllerSpec extends Specification {
private static final String STATE = 'some-state'
private static final String CODE = 'some-code'
private static final String ERROR = 'some-error'
private static final String REDIRECT_URL = 'https://redirect.com'
@Inject Gru gru
@MockBean(GoogleAnalyticsConnectService)
GoogleAnalyticsConnectService googleAnalyticsConnectService = Mock()</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre>@MicronautTest
@Property(name = "mock.jwt.identity.enabled", value = "true")
class ConnectCallbackControllerTest {
private static final String STATE = "some-state";
private static final String CODE = "some-code";
private static final String ERROR = "some-error";
private static final String REDIRECT_URL = "https://redirect.com";
private static final GoogleAnalyticsConnectService MOCK_CONNECT_SERVICE = Mockito.mock(GoogleAnalyticsConnectService.class);
@Inject
Gru gru;
@MockBean(GoogleAnalyticsConnectService.class)
GoogleAnalyticsConnectService googleAnalyticsConnectService() {
return MOCK_CONNECT_SERVICE;
}</pre>
</div>
</div>
<div class="summary">
<p><strong>Changes:</strong> Removed extends Specification. Converted Groovy Mock() to static Mockito.mock(). Changed @MockBean to method-based factory pattern returning static mock. Added semicolons and .class suffix.</p>
</div>
</div>
</div>
<!-- Section: Test - Oauth callback -->
<div class="section">
<div class="section-header" onclick="toggleSection(this)">
<h2>🧪 Oauth callback</h2>
<span class="toggle">▼</span>
</div>
<div class="section-content">
<div class="diff-container">
<div class="diff-panel left">
<h3>Spock (Groovy)</h3>
<pre>void 'Oauth callback'() {
when:
gru.test {
get "/oauth/callback", {
params state: STATE, code: CODE, error: ERROR
}
expect {
status MOVED_PERMANENTLY
redirect REDIRECT_URL
}
}
then:
gru.verify()
1 * googleAnalyticsConnectService.callback(STATE, CODE, ERROR) >> new URI(REDIRECT_URL)
}</pre>
</div>
<div class="diff-panel right">
<h3>JUnit 5 (Java)</h3>
<pre>@Test
void oauth_callback() throws Throwable {
// given
when(MOCK_CONNECT_SERVICE.callback(STATE, CODE, ERROR)).thenReturn(new URI(REDIRECT_URL));
// when
gru.test(test -> test
.get("/oauth/callback", req -> req
.param("state", STATE)
.param("code", CODE)
.param("error", ERROR))
.expect(resp -> resp
.status(301)
.redirect(REDIRECT_URL)));
// then
gru.verify();
verify(MOCK_CONNECT_SERVICE).callback(STATE, CODE, ERROR);
}</pre>
</div>
</div>
<div class="summary">
<p><strong>Changes:</strong> Added @Test annotation. Converted Groovy string method name to snake_case. Moved mock stubbing (1 * ... >> ...) to given block using when().thenReturn(). Replaced Spock params map with individual .param() calls. Replaced MOVED_PERMANENTLY constant with explicit 301 status code. Added verify() for mock interaction check. Added throws Throwable for Gru test method.</p>
</div>
</div>
</div>
<script>
function toggleSection(header) {
const content = header.nextElementSibling;
const toggle = header.querySelector('.toggle');
content.classList.toggle('collapsed');
toggle.textContent = content.classList.contains('collapsed') ? '▶' : '▼';
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment