All skills
kotlin avatar

/kotlin-tooling-java-to-kotlin

@8fc58af official
by kotlinkotlin/kotlin-agent-skills1.1k stars
42

Use when converting Java source files to idiomatic Kotlin, when user mentions "java to kotlin", "j2k", "convert java", "migrate java to kotlin", or when working with .java files that need to become .kt files. Handles framework-aware conversion for Spring, Lombok, Hibernate, Jackson, Micronaut, Quarkus, Dagger/Hilt, RxJava, JUnit, Guice, Retrofit, and Mockito.

Use this Skill: https://skilld.dev/gh/kotlin/kotlin-agent-skills/kotlin-tooling-java-to-kotlin

This session only. Nothing lands on disk.

referencesframeworksMOCKITO.md

≈2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Mockito to MockK Conversion Guide

When This Applies

Detected when imports match org.mockito.*.

While Mockito works in Kotlin, MockK is the idiomatic Kotlin mocking library. Convert to MockK when the project already uses MockK or is doing a full Kotlin migration. If the project wants to keep Mockito, convert only the Java syntax to Kotlin syntax using the mockito-kotlin helper library.

Key Rules

1. MockK conversion table

Mockito MockK
Mockito.mock(Foo.class) mockk<Foo>()
@Mock Foo foo @MockK lateinit var foo: Foo (with @ExtendWith(MockKExtension::class))
when(foo.bar()).thenReturn(x) every { foo.bar() } returns x
when(foo.bar()).thenThrow(e) every { foo.bar() } throws e
when(foo.bar()).thenAnswer { } every { foo.bar() } answers { }
doNothing().when(foo).bar() justRun { foo.bar() }
verify(foo).bar() verify { foo.bar() }
verify(foo, times(2)).bar() verify(exactly = 2) { foo.bar() }
verify(foo, never()).bar() verify(exactly = 0) { foo.bar() }
ArgumentCaptor<T> slot<T>() and capture(slot)
any() any()
eq(x) eq(x) (often not needed — MockK matches exact values by default)
Mockito.spy(obj) spyk(obj)
@InjectMocks No direct equivalent — use constructor injection
verifyNoMoreInteractions(foo) confirmVerified(foo)

2. Coroutine support in MockK

For suspending functions, use coEvery and coVerify instead of every and verify:

coEvery { foo.suspendBar() } returns x
coVerify { foo.suspendBar() }

3. Keeping Mockito (syntax-only conversion)

If keeping Mockito, use the mockito-kotlin library (org.mockito.kotlin) for Kotlin-friendly wrappers:

  • mock<Foo>() instead of Mockito.mock(Foo::class.java) — uses reified generics.
  • whenever(foo.bar()) instead of Mockito.`when`(foo.bar()) — avoids backtick- escaping when (it is a Kotlin keyword).
  • argumentCaptor<T>() — type-safe captor via reified generics.
  • any() — properly handles Kotlin's non-null types.

4. Relaxed mocks

MockK supports relaxed mocks that return default values without explicit stubbing: mockk<Foo>(relaxed = true). This has no direct Mockito equivalent (Mockito's RETURNS_DEFAULTS is the closest).


Example 1: Converting to MockK

Java Input

package com.acme.service;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.ArgumentMatchers.anyLong;

import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

/**
 * Tests for OrderService using Mockito mocks.
 */
public class OrderServiceTest {

    private UserRepository userRepository;
    private OrderRepository orderRepository;
    private OrderService orderService;

    @Before
    public void setUp() {
        userRepository = mock(UserRepository.class);
        orderRepository = mock(OrderRepository.class);
        orderService = new OrderService(userRepository, orderRepository);
    }

    @Test
    public void testCreateOrderForUser() {
        User user = new User(1L, "Alice");
        when(userRepository.findById(1L)).thenReturn(user);

        orderService.createOrder(1L, "ITEM-100");

        ArgumentCaptor<Order> captor = ArgumentCaptor.forClass(Order.class);
        verify(orderRepository).save(captor.capture());
        assertEquals("ITEM-100", captor.getValue().getItemCode());
        assertEquals(1L, captor.getValue().getUserId());
    }

    @Test
    public void testGetOrderCount() {
        when(orderRepository.countByUserId(anyLong())).thenReturn(5);

        int count = orderService.getOrderCount(1L);

        assertEquals(5, count);
        verify(orderRepository).countByUserId(1L);
    }
}

Kotlin Output (MockK)

package com.acme.service

import io.mockk.every
import io.mockk.mockk
import io.mockk.slot
import io.mockk.verify
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

/**
 * Tests for OrderService using MockK mocks.
 */
class OrderServiceTest {

    private val userRepository = mockk<UserRepository>()
    private val orderRepository = mockk<OrderRepository>()
    private val orderService = OrderService(userRepository, orderRepository)

    @Test
    fun `should create order for user`() {
        val user = User(1L, "Alice")
        every { userRepository.findById(1L) } returns user
        every { orderRepository.save(any()) } returns Unit

        orderService.createOrder(1L, "ITEM-100")

        val orderSlot = slot<Order>()
        verify { orderRepository.save(capture(orderSlot)) }
        assertEquals("ITEM-100", orderSlot.captured.itemCode)
        assertEquals(1L, orderSlot.captured.userId)
    }

    @Test
    fun `should return order count`() {
        every { orderRepository.countByUserId(any()) } returns 5

        val count = orderService.getOrderCount(1L)

        assertEquals(5, count)
        verify { orderRepository.countByUserId(1L) }
    }
}

Key points:

  • mock(Foo.class) → mockk<Foo>() using reified generics.
  • @Before setUp is eliminated — mocks are initialized inline with property declarations. This works because MockK mocks do not require a runner.
  • when(...).thenReturn(...) → every { ... } returns ....
  • ArgumentCaptor → slot<T>() with capture(slot), accessed via slot.captured.
  • anyLong() → any() (MockK's any() handles all types).
  • verify(foo).bar() → verify { foo.bar() }.

Example 2: Keeping Mockito (mockito-kotlin syntax)

Java Input

package com.acme.service;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import org.junit.Before;
import org.junit.Test;

/**
 * Tests for PricingService using Mockito.
 */
public class PricingServiceTest {

    private PriceRepository priceRepository;
    private PricingService pricingService;

    @Before
    public void setUp() {
        priceRepository = mock(PriceRepository.class);
        pricingService = new PricingService(priceRepository);
    }

    @Test
    public void testGetPrice() {
        when(priceRepository.findPriceByItemCode("ITEM-1")).thenReturn(9.99);
        double price = pricingService.getPrice("ITEM-1");
        assertEquals(9.99, price, 0.001);
        verify(priceRepository).findPriceByItemCode("ITEM-1");
    }
}

Kotlin Output (mockito-kotlin)

package com.acme.service

import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import kotlin.test.assertEquals

/**
 * Tests for PricingService using Mockito.
 */
class PricingServiceTest {

    private val priceRepository = mock<PriceRepository>()
    private val pricingService = PricingService(priceRepository)

    @Test
    fun `should return price for item`() {
        whenever(priceRepository.findPriceByItemCode("ITEM-1")).thenReturn(9.99)

        val price = pricingService.getPrice("ITEM-1")

        assertEquals(9.99, price, 0.001)
        verify(priceRepository).findPriceByItemCode("ITEM-1")
    }
}

Key points:

  • mock(Foo.class) → mock<Foo>() from org.mockito.kotlin (reified generics).
  • when(...) → whenever(...) to avoid backtick-escaping the when keyword.
  • verify stays the same — org.mockito.kotlin.verify wraps Mockito's verify.
  • The setUp method is eliminated — mocks are initialized inline.
  • assertEquals with a delta parameter works the same way from kotlin.test.

Source: SKILL.md on GitHub

No alerts16d4 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides a methodology for converting Java source code to Kotlin. While the logic is sound and focused on development tasks, it possesses an indirect prompt injection surface by processing untrusted source code and performing file system operations.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 8fc58af. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 weeks ago.

Activeupdated 7 months ago
metadata
{
  "author": "JetBrains",
  "version": "1.0.0"
}
  • kotlin
  • java
  • migration
  • spring
  • hibernate
  • jackson
  • junit
  • rxjava
  • retrofit
  • mockito
  • conversion

README badge

README badge for kotlin/kotlin-agent-skills/kotlin-tooling-java-to-kotlin

Converts Java source files to idiomatic Kotlin using a structured 4-step methodology with framework-aware handling for Spring, Lombok, Hibernate, Jackson, Micronaut, Quarkus, Dagger/Hilt, RxJava, JUnit, Guice, Retrofit, and Mockito. Preserves git history through two-phase renames and supports batch conversion with dependency ordering.

Generated from the current SKILL.md.

What frameworks does this skill handle?
Spring, Lombok, Hibernate, Jackson, Micronaut, Quarkus, Dagger/Hilt, RxJava, JUnit, Guice, Retrofit, and Mockito. The skill detects which frameworks are in use by scanning import statements and loads only the relevant framework guides.
Does this skill preserve git blame history?
Yes. It uses a two-phase approach: first rename the file with `git mv`, then replace the content in a separate commit so the rename is tracked separately from the conversion changes.
Can this skill convert multiple Java files at once?
Yes. For batch conversions, it sorts files by dependency order (leaf files first), converts one at a time through the full workflow, and updates cross-references as needed.
What happens if conversion fails the verification step?
The skill reverts to the previous conversion step and retries. It checks five invariants at each step and verifies output by compilation, tests, and annotation site targets.
Does this handle Java interop edge cases like platform types and checked exceptions?
Yes. The skill documents and handles Kotlin keyword conflicts, SAM conversion ambiguity, platform types, @JvmStatic/@JvmField/@JvmOverloads, checked exceptions, and wildcard generics in a separate known-issues reference.

Generated from the current SKILL.md. These answers refresh after source changes.