YongGoose commented on code in PR #7482: URL: https://github.com/apache/incubator-seata/pull/7482#discussion_r2178793282
########## spring/src/test/java/org/apache/seata/spring/kt/TransactionScopeTest.kt: ########## @@ -72,62 +78,215 @@ class TransactionScopeTest { return globalStatus } }) + + // Clean up context + RootContext.unbind() } + @AfterEach + fun tearDown() { + // Clean up global state to avoid affecting other tests + RootContext.unbind() + + // Restore original TransactionManager + backupTransactionManager?.let { TransactionManagerHolder.set(it) } + } + /** + * Test that @GlobalTransactional does not work properly in coroutines + * + * Due to coroutine thread switching, @GlobalTransactional annotation cannot maintain + * transaction context, this is expected behavior, not a bug. + */ @Test @Throws(NoSuchMethodException::class) - fun testGlobalTransactional() { - RootContext.bind(DEFAULT_XID) - val globalTransactionContext = GlobalTransactionContext.getCurrentOrCreate() - globalTransactionContext.begin() - println(RootContext.getXID()) - val mockClassAnnotation = MockMethodAnnotation() - val xid = runBlocking { - mockClassAnnotation.doBiz() + fun testGlobalTransactionalInCoroutineNotWorking() { + // Test that @GlobalTransactional does not work properly in coroutines (expected behavior) + try { + RootContext.bind(DEFAULT_XID) + val globalTransactionContext = GlobalTransactionContext.getCurrentOrCreate() + globalTransactionContext.begin() + + val mockClassAnnotation = MockMethodAnnotationWithoutContext() + val xid = runBlocking { + mockClassAnnotation.doBiz() + } + + // Verify that @GlobalTransactional cannot maintain transaction context in coroutines due to context switching + Assertions.assertNull(xid, "@GlobalTransactional should not work in coroutines due to context switching") + } finally { + RootContext.unbind() } - Assertions.assertNotNull(xid) } - private open class MockMethodAnnotation { - /** - * use io coroutine - */ - @GlobalTransactional(name = "doBiz") - suspend fun doBiz(): String? = io { - return@io RootContext.getXID() + /** + * Test transaction propagation when used with TransactionCoroutineContext + * + * By explicitly adding TransactionCoroutineContext, transaction context can be + * properly propagated between coroutines. + */ + @Test + @Throws(NoSuchMethodException::class) + fun testGlobalTransactionalWithCoroutineContext() { + // Test that @GlobalTransactional works properly with TransactionCoroutineContext + try { + RootContext.bind(DEFAULT_XID) + val globalTransactionContext = GlobalTransactionContext.getCurrentOrCreate() + globalTransactionContext.begin() + + val mockClassAnnotation = MockMethodAnnotationWithContext() + val xid = runBlocking { + mockClassAnnotation.doBiz() + } + + // Using TransactionCoroutineContext should be able to maintain transaction context + Assertions.assertNotNull(xid, "@GlobalTransactional should work with TransactionCoroutineContext") + Assertions.assertEquals(DEFAULT_XID, xid) + } finally { + RootContext.unbind() } + } - suspend fun <T> io(block: suspend CoroutineScope.() -> T): T { - return withContext(Dispatchers.IO, block) + @Test + @Throws(NoSuchMethodException::class) + fun testTransactionScope() { + // Due to TransactionManagerHolder singleton issues, we test basic functionality of transactionScope + // instead of relying on the real transaction manager + try { + var capturedXid: String? = null + + // Simulate transactionScope behavior with simplified logic + runBlocking { + // Manually bind an XID to simulate transaction start + RootContext.bind(DEFAULT_XID) + + // Propagate transaction in coroutine context + withContext(org.apache.seata.spring.kt.support.TransactionCoroutineContext()) { + capturedXid = RootContext.getXID() + } + + // Clean up + RootContext.unbind() + } + + // Verify that transaction context can be propagated in coroutines + Assertions.assertNotNull(capturedXid, "TransactionCoroutineContext should propagate transaction context") + Assertions.assertEquals(DEFAULT_XID, capturedXid) + } catch (e: Exception) { + throw e } Review Comment: Seems reasonable! ########## spring/src/test/java/org/apache/seata/spring/kt/TransactionScopeTest.kt: ########## @@ -72,62 +78,215 @@ class TransactionScopeTest { return globalStatus } }) + + // Clean up context + RootContext.unbind() } + @AfterEach + fun tearDown() { + // Clean up global state to avoid affecting other tests + RootContext.unbind() + + // Restore original TransactionManager + backupTransactionManager?.let { TransactionManagerHolder.set(it) } + } + /** + * Test that @GlobalTransactional does not work properly in coroutines + * + * Due to coroutine thread switching, @GlobalTransactional annotation cannot maintain + * transaction context, this is expected behavior, not a bug. + */ @Test @Throws(NoSuchMethodException::class) - fun testGlobalTransactional() { - RootContext.bind(DEFAULT_XID) - val globalTransactionContext = GlobalTransactionContext.getCurrentOrCreate() - globalTransactionContext.begin() - println(RootContext.getXID()) - val mockClassAnnotation = MockMethodAnnotation() - val xid = runBlocking { - mockClassAnnotation.doBiz() + fun testGlobalTransactionalInCoroutineNotWorking() { + // Test that @GlobalTransactional does not work properly in coroutines (expected behavior) + try { + RootContext.bind(DEFAULT_XID) + val globalTransactionContext = GlobalTransactionContext.getCurrentOrCreate() + globalTransactionContext.begin() + + val mockClassAnnotation = MockMethodAnnotationWithoutContext() + val xid = runBlocking { + mockClassAnnotation.doBiz() + } + + // Verify that @GlobalTransactional cannot maintain transaction context in coroutines due to context switching + Assertions.assertNull(xid, "@GlobalTransactional should not work in coroutines due to context switching") + } finally { + RootContext.unbind() } - Assertions.assertNotNull(xid) } - private open class MockMethodAnnotation { - /** - * use io coroutine - */ - @GlobalTransactional(name = "doBiz") - suspend fun doBiz(): String? = io { - return@io RootContext.getXID() + /** + * Test transaction propagation when used with TransactionCoroutineContext + * + * By explicitly adding TransactionCoroutineContext, transaction context can be + * properly propagated between coroutines. + */ + @Test + @Throws(NoSuchMethodException::class) + fun testGlobalTransactionalWithCoroutineContext() { + // Test that @GlobalTransactional works properly with TransactionCoroutineContext + try { + RootContext.bind(DEFAULT_XID) + val globalTransactionContext = GlobalTransactionContext.getCurrentOrCreate() + globalTransactionContext.begin() + + val mockClassAnnotation = MockMethodAnnotationWithContext() + val xid = runBlocking { + mockClassAnnotation.doBiz() + } + + // Using TransactionCoroutineContext should be able to maintain transaction context + Assertions.assertNotNull(xid, "@GlobalTransactional should work with TransactionCoroutineContext") + Assertions.assertEquals(DEFAULT_XID, xid) + } finally { + RootContext.unbind() } + } - suspend fun <T> io(block: suspend CoroutineScope.() -> T): T { - return withContext(Dispatchers.IO, block) + @Test + @Throws(NoSuchMethodException::class) + fun testTransactionScope() { + // Due to TransactionManagerHolder singleton issues, we test basic functionality of transactionScope + // instead of relying on the real transaction manager + try { + var capturedXid: String? = null + + // Simulate transactionScope behavior with simplified logic + runBlocking { + // Manually bind an XID to simulate transaction start + RootContext.bind(DEFAULT_XID) + + // Propagate transaction in coroutine context + withContext(org.apache.seata.spring.kt.support.TransactionCoroutineContext()) { Review Comment: ditto -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org For additional commands, e-mail: notifications-h...@seata.apache.org