From faba78db7af37dfc51dcbc9a1b816b843409d225 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Tue, 20 Jan 2026 15:32:02 -0800 Subject: [PATCH 1/2] Add test for missing @workflow_run_operation decorator Add a test case that validates a clear TypeError is raised when a handler method lacks the @workflow_run_operation decorator but the service interface expects an operation. Also fix the error branch of the test to use consistent service= keyword argument. Co-Authored-By: Claude Opus 4.5 --- .../test_handler_interface_implementation.py | 20 ++++++++++++++++++- tests/nexus/test_workflow_caller.py | 3 --- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/tests/nexus/test_handler_interface_implementation.py b/tests/nexus/test_handler_interface_implementation.py index 35289e188..1a8295408 100644 --- a/tests/nexus/test_handler_interface_implementation.py +++ b/tests/nexus/test_handler_interface_implementation.py @@ -44,11 +44,29 @@ async def op( error_message = None +class MissingWorkflowRunDecorator(_InterfaceImplementationTestCase): + """Missing @workflow_run_operation decorator raises appropriate error.""" + + @nexusrpc.service + class Interface: + my_workflow_op: nexusrpc.Operation[str, int] + + class Impl: + # Method exists but MISSING @workflow_run_operation decorator + async def my_workflow_op( + self, ctx: WorkflowRunOperationContext, input: str + ) -> nexus.WorkflowHandle[int]: + raise NotImplementedError + + error_message = "does not implement an operation with method name 'my_workflow_op'" + + @pytest.mark.parametrize( "test_case", [ ValidImpl, ValidWorkflowRunImpl, + MissingWorkflowRunDecorator, ], ) def test_service_decorator_enforces_interface_conformance( @@ -56,7 +74,7 @@ def test_service_decorator_enforces_interface_conformance( ): if test_case.error_message: with pytest.raises(Exception) as ei: - nexusrpc.handler.service_handler(test_case.Interface)(test_case.Impl) + nexusrpc.handler.service_handler(service=test_case.Interface)(test_case.Impl) err = ei.value assert test_case.error_message in str(err) else: diff --git a/tests/nexus/test_workflow_caller.py b/tests/nexus/test_workflow_caller.py index 273581302..4d54c6123 100644 --- a/tests/nexus/test_workflow_caller.py +++ b/tests/nexus/test_workflow_caller.py @@ -902,9 +902,6 @@ async def run( return await nexus_client.execute_operation(service_cls.op, None) # type: ignore -# TODO(nexus-prerelease): check missing decorator behavior - - async def test_service_interface_and_implementation_names( client: Client, env: WorkflowEnvironment ): From 6ca13faf154fed4ca07d46f630f52af802321463 Mon Sep 17 00:00:00 2001 From: Alex Mazzeo Date: Tue, 20 Jan 2026 16:06:05 -0800 Subject: [PATCH 2/2] Fix format and linter issues --- tests/nexus/test_handler_interface_implementation.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/nexus/test_handler_interface_implementation.py b/tests/nexus/test_handler_interface_implementation.py index 1a8295408..f20f25a04 100644 --- a/tests/nexus/test_handler_interface_implementation.py +++ b/tests/nexus/test_handler_interface_implementation.py @@ -54,7 +54,7 @@ class Interface: class Impl: # Method exists but MISSING @workflow_run_operation decorator async def my_workflow_op( - self, ctx: WorkflowRunOperationContext, input: str + self, _ctx: WorkflowRunOperationContext, _input: str ) -> nexus.WorkflowHandle[int]: raise NotImplementedError @@ -74,7 +74,9 @@ def test_service_decorator_enforces_interface_conformance( ): if test_case.error_message: with pytest.raises(Exception) as ei: - nexusrpc.handler.service_handler(service=test_case.Interface)(test_case.Impl) + nexusrpc.handler.service_handler(service=test_case.Interface)( + test_case.Impl + ) err = ei.value assert test_case.error_message in str(err) else: