using AyCode.Core.Tests.TestModels; using AyCode.Services.Server.SignalRs; using AyCode.Services.Server.Tests.SignalRs; namespace AyCode.Services.Server.Tests; [TestClass] public class InvokeMethodExtensionTests { #region InvokeMethod Unit Tests [TestMethod] public void InvokeMethod_SyncMethod_ReturnsValue() { var service = new TestSignalRService2(); var methodInfo = typeof(TestSignalRService2).GetMethod("HandleSingleInt")!; var result = methodInfo.InvokeMethod(service, 42); Assert.AreEqual("42", result); } [TestMethod] public void InvokeMethod_AsyncTaskTMethod_ReturnsUnwrappedValue() { var service = new TestSignalRService2(); var methodInfo = typeof(TestSignalRService2).GetMethod("HandleAsyncString")!; var result = methodInfo.InvokeMethod(service, "Test"); Assert.IsNotNull(result, "InvokeMethod should unwrap Task and return the result"); Assert.AreEqual("Async: Test", result); } [TestMethod] public void InvokeMethod_AsyncTaskTMethod_WithComplexObject_ReturnsUnwrappedValue() { var service = new TestSignalRService2(); var methodInfo = typeof(TestSignalRService2).GetMethod("HandleAsyncTestOrderItem")!; var input = new TestOrderItem { Id = 1, ProductName = "Widget", Quantity = 5, UnitPrice = 10m }; var result = methodInfo.InvokeMethod(service, input); Assert.IsNotNull(result, "InvokeMethod should unwrap Task and return the result"); Assert.IsInstanceOfType(result, typeof(TestOrderItem)); var item = (TestOrderItem)result; Assert.AreEqual("Async: Widget", item.ProductName); Assert.AreEqual(15, item.Quantity); } [TestMethod] public void InvokeMethod_AsyncTaskTMethod_WithInt_ReturnsUnwrappedValue() { var service = new TestSignalRService2(); var methodInfo = typeof(TestSignalRService2).GetMethod("HandleAsyncInt")!; var result = methodInfo.InvokeMethod(service, 42); Assert.IsNotNull(result, "InvokeMethod should unwrap Task and return the result"); Assert.AreEqual(84, result); } /// /// CRITICAL: Tests Task.FromResult() - methods returning Task without async keyword. /// This was the root cause of the production bug where Task wrapper was serialized. /// [TestMethod] public void InvokeMethod_TaskFromResult_ReturnsUnwrappedValue() { var service = new TestSignalRService2(); var methodInfo = typeof(TestSignalRService2).GetMethod("HandleTaskFromResultString")!; var result = methodInfo.InvokeMethod(service, "Test"); Assert.IsNotNull(result, "InvokeMethod should unwrap Task.FromResult and return the result"); Assert.AreEqual("FromResult: Test", result); } [TestMethod] public void InvokeMethod_TaskFromResult_WithComplexObject_ReturnsUnwrappedValue() { var service = new TestSignalRService2(); var methodInfo = typeof(TestSignalRService2).GetMethod("HandleTaskFromResultTestOrderItem")!; var input = new TestOrderItem { Id = 1, ProductName = "Widget", Quantity = 5, UnitPrice = 10m }; var result = methodInfo.InvokeMethod(service, input); Assert.IsNotNull(result, "InvokeMethod should unwrap Task.FromResult and return the result"); Assert.IsInstanceOfType(result, typeof(TestOrderItem)); var item = (TestOrderItem)result; Assert.AreEqual("FromResult: Widget", item.ProductName); Assert.AreEqual(10, item.Quantity); // Doubled } [TestMethod] public void InvokeMethod_TaskFromResult_WithInt_ReturnsUnwrappedValue() { var service = new TestSignalRService2(); var methodInfo = typeof(TestSignalRService2).GetMethod("HandleTaskFromResultInt")!; var result = methodInfo.InvokeMethod(service, 42); Assert.IsNotNull(result, "InvokeMethod should unwrap Task.FromResult and return the result"); Assert.AreEqual(84, result); } [TestMethod] public void InvokeMethod_NonGenericTask_ReturnsNull() { var service = new TestSignalRService2(); var methodInfo = typeof(TestSignalRService2).GetMethod("HandleTaskFromResultNoParams")!; var result = methodInfo.InvokeMethod(service); // Task.CompletedTask returns a completed Task, InvokeMethod waits for it // The result should be null since it's a non-generic Task (no return value) // Note: Task.CompletedTask internally may be Task but we don't expose it // The important thing is the method completes without exception } #endregion }