diff --git a/pyproject.toml b/pyproject.toml index 7d6ebffff..7cc210869 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath" -version = "2.2.33" +version = "2.2.34" description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools." readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" diff --git a/src/uipath/_cli/_evals/_models/_evaluation_set.py b/src/uipath/_cli/_evals/_models/_evaluation_set.py index 78a2fb6f5..b610a23d3 100644 --- a/src/uipath/_cli/_evals/_models/_evaluation_set.py +++ b/src/uipath/_cli/_evals/_models/_evaluation_set.py @@ -103,6 +103,12 @@ class InputMockingStrategy(BaseModel): class MockingArgument(BaseModel): args: list[Any] = Field(default_factory=lambda: [], alias="args") kwargs: dict[str, Any] = Field(default_factory=lambda: {}, alias="kwargs") + match_any_additional_args: bool = Field( + default=False, alias="matchAnyAdditionalArgs" + ) + match_any_additional_kwargs: bool = Field( + default=False, alias="matchAnyAdditionalKwargs" + ) class MockingAnswerType(str, Enum): diff --git a/src/uipath/_cli/_evals/mocks/mockito_mocker.py b/src/uipath/_cli/_evals/mocks/mockito_mocker.py index 3d4b7eeb9..c68917b7f 100644 --- a/src/uipath/_cli/_evals/mocks/mockito_mocker.py +++ b/src/uipath/_cli/_evals/mocks/mockito_mocker.py @@ -4,6 +4,8 @@ from typing import Any, Callable from mockito import ( # type: ignore[import-untyped] # explicit ignore + ARGS, + KWARGS, invocation, mocking, ) @@ -78,6 +80,11 @@ def __init__(self, evaluation_item: EvaluationItem): args = resolved_args if resolved_args is not None else [] kwargs = resolved_kwargs if resolved_kwargs is not None else {} + if behavior.arguments.match_any_additional_kwargs: + kwargs = kwargs | KWARGS + if behavior.arguments.match_any_additional_args: + args = args + ARGS + stubbed = invocation.StubbedInvocation(mock_obj, behavior.function)( *args, **kwargs, diff --git a/tests/cli/eval/mocks/test_mocks.py b/tests/cli/eval/mocks/test_mocks.py index fb9517346..66f0a74a5 100644 --- a/tests/cli/eval/mocks/test_mocks.py +++ b/tests/cli/eval/mocks/test_mocks.py @@ -135,6 +135,91 @@ async def foofoo(*args, **kwargs): assert await foo(x=2) == "bar1" +def test_mockito_mockable_anyargs_sync(): + # Arrange + @mockable() + def foo(*args, **kwargs): + raise NotImplementedError() + + evaluation_item: dict[str, Any] = { + "id": "evaluation-id", + "name": "Mock foo", + "inputs": {}, + "evaluationCriterias": { + "ExactMatchEvaluator": None, + }, + "mockingStrategy": { + "type": "mockito", + "behaviors": [ + { + "function": "foo", + "arguments": { + "args": [], + "kwargs": {}, + "matchAnyAdditionalArgs": True, + "matchAnyAdditionalKwargs": True, + }, + "then": [ + {"type": "return", "value": "bar1"}, + ], + } + ], + }, + } + evaluation = EvaluationItem(**evaluation_item) + assert isinstance(evaluation.mocking_strategy, MockitoMockingStrategy) + + # Act & Assert + set_execution_context(evaluation, _mock_span_collector, "test-execution-id") + assert foo(x=1) == "bar1" + assert foo(x="x") == "bar1" + assert foo() == "bar1" + assert foo(1) == "bar1" + + +@pytest.mark.asyncio +async def test_mockito_mockable_anyargs_async(): + # Arrange + @mockable() + async def foo(*args, **kwargs): + raise NotImplementedError() + + evaluation_item: dict[str, Any] = { + "id": "evaluation-id", + "name": "Mock foo", + "inputs": {}, + "evaluationCriterias": { + "ExactMatchEvaluator": None, + }, + "mockingStrategy": { + "type": "mockito", + "behaviors": [ + { + "function": "foo", + "arguments": { + "args": [], + "kwargs": {}, + "matchAnyAdditionalArgs": True, + "matchAnyAdditionalKwargs": True, + }, + "then": [ + {"type": "return", "value": "bar1"}, + ], + } + ], + }, + } + evaluation = EvaluationItem(**evaluation_item) + assert isinstance(evaluation.mocking_strategy, MockitoMockingStrategy) + + # Act & Assert + set_execution_context(evaluation, _mock_span_collector, "test-execution-id") + assert await foo(x=1) == "bar1" + assert await foo(x="x") == "bar1" + assert await foo() == "bar1" + assert await foo(1) == "bar1" + + @pytest.mark.httpx_mock(assert_all_responses_were_requested=False) def test_llm_mockable_sync(httpx_mock: HTTPXMock, monkeypatch: MonkeyPatch): monkeypatch.setenv("UIPATH_URL", "https://example.com") diff --git a/uv.lock b/uv.lock index 0b21dda20..2900e99ca 100644 --- a/uv.lock +++ b/uv.lock @@ -2477,7 +2477,7 @@ wheels = [ [[package]] name = "uipath" -version = "2.2.33" +version = "2.2.34" source = { editable = "." } dependencies = [ { name = "click" },