def test_consume_verify_rehearsals_ignore_extra_args() -> None: """It should be able to pop a slice off the stack, retaining order.""" subject = SpyLog() call_1 = SpyEvent(spy_id=1, spy_name="spy_1", payload=SpyCall(args=(), kwargs={})) call_2 = SpyEvent(spy_id=2, spy_name="spy_2", payload=SpyCall(args=(), kwargs={})) subject.push(call_1) subject.push(call_2) result = subject.consume_verify_rehearsals(count=2, ignore_extra_args=True) assert result == [ VerifyRehearsal( spy_id=1, spy_name="spy_1", payload=SpyCall(args=(), kwargs={}, ignore_extra_args=True), ), VerifyRehearsal( spy_id=2, spy_name="spy_2", payload=SpyCall(args=(), kwargs={}, ignore_extra_args=True), ), ]
def test_verify( decoy: Decoy, spy_log: SpyLog, verifier: Verifier, subject: DecoyCore, ) -> None: """It should be able to verify a call.""" spy_id = 42 rehearsal = VerifyRehearsal(spy_id=spy_id, spy_name="my_spy", payload=SpyCall(args=(), kwargs={})) call = SpyEvent(spy_id=spy_id, spy_name="my_spy", payload=SpyCall(args=(), kwargs={})) decoy.when( spy_log.consume_verify_rehearsals( count=1, ignore_extra_args=False)).then_return([rehearsal]) decoy.when(spy_log.get_calls_to_verify([spy_id])).then_return([call]) subject.verify("__rehearsal__", times=None, ignore_extra_args=False) decoy.verify( verifier.verify(rehearsals=[rehearsal], calls=[call], times=None))
def test_push_and_consume_when_rehearsal() -> None: """It should be able to push and pop from the stack.""" subject = SpyLog() call = SpyEvent( spy_id=42, spy_name="my_spy", payload=SpyCall(args=(), kwargs={}), ) subject.push(call) result = subject.consume_when_rehearsal(ignore_extra_args=False) assert isinstance(result, WhenRehearsal) assert call == result
def test_push_and_consume_prop_rehearsal_for_prop() -> None: """It should be able to push and consume a prop rehearsal for more rehearsals.""" subject = SpyLog() event = SpyEvent( spy_id=42, spy_name="my_spy", payload=SpyPropAccess(prop_name="my_prop", access_type=PropAccessType.GET), ) subject.push(event) result = subject.consume_prop_rehearsal() assert isinstance(result, PropRehearsal) assert result == event
def test_push_and_consume_prop_rehearsal_for_when() -> None: """It should be able to push and consume a prop rehearsal for stubbing.""" subject = SpyLog() event = SpyEvent( spy_id=42, spy_name="my_spy", payload=SpyPropAccess(prop_name="my_prop", access_type=PropAccessType.GET), ) subject.push(event) result = subject.consume_when_rehearsal(ignore_extra_args=False) assert isinstance(result, WhenRehearsal) assert result == event
def test_when_then_return_multiple_values( decoy: Decoy, spy_log: SpyLog, stub_store: StubStore, subject: DecoyCore, ) -> None: """It should add multiple return values to a stub.""" rehearsal = WhenRehearsal(spy_id=1, spy_name="my_spy", payload=SpyCall(args=(), kwargs={})) decoy.when(spy_log.consume_when_rehearsal( ignore_extra_args=False)).then_return(rehearsal) result = subject.when(0, ignore_extra_args=False) result.then_return(42, 43, 44) decoy.verify( stub_store.add( rehearsal=rehearsal, behavior=StubBehavior(return_value=44, once=False), ), stub_store.add( rehearsal=rehearsal, behavior=StubBehavior(return_value=43, once=True), ), stub_store.add( rehearsal=rehearsal, behavior=StubBehavior(return_value=42, once=True), ), )
def test_consume_when_rehearsal_raises_empty_error() -> None: """It should raise an error if the stack is empty on pop.""" subject = SpyLog() with pytest.raises(MissingRehearsalError): subject.consume_when_rehearsal(ignore_extra_args=False) call = SpyEvent( spy_id=42, spy_name="my_spy", payload=SpyCall(args=(), kwargs={}), ) subject.push(call) subject.consume_when_rehearsal(ignore_extra_args=False) with pytest.raises(MissingRehearsalError): subject.consume_when_rehearsal(ignore_extra_args=False)
def test_get_calls_to_verify_skips_prop_gets() -> None: """It does not return prop getters for verification.""" subject = SpyLog() call_1 = SpyEvent( spy_id=101, spy_name="spy_1", payload=SpyPropAccess(prop_name="child", access_type=PropAccessType.GET), ) call_2 = PropRehearsal( spy_id=101, spy_name="spy_1", payload=SpyPropAccess(prop_name="child", access_type=PropAccessType.GET), ) call_3 = SpyEvent( spy_id=102, spy_name="spy_1.child", payload=SpyCall(args=(2, ), kwargs={}), ) call_4 = SpyEvent( spy_id=102, spy_name="spy_1.child", payload=SpyPropAccess(prop_name="fizz", access_type=PropAccessType.DELETE), ) subject.push(call_1) subject.push(call_2) subject.push(call_3) subject.push(call_4) result = subject.get_calls_to_verify([101, 102]) assert result == [call_3, call_4]
def test_reset( decoy: Decoy, spy_log: SpyLog, stub_store: StubStore, warning_checker: WarningChecker, subject: DecoyCore, ) -> None: """It should reset the stores.""" call = SpyEvent(spy_id=1, spy_name="my_spy", payload=SpyCall(args=(), kwargs={})) decoy.when(spy_log.get_all()).then_return([call]) subject.reset() decoy.verify( warning_checker.check([call]), spy_log.clear(), stub_store.clear(), )
def test_verify_multiple_calls( decoy: Decoy, spy_log: SpyLog, verifier: Verifier, subject: DecoyCore, ) -> None: """It should be able to verify a call.""" spy_id_1 = 42 spy_id_2 = 9001 rehearsals = [ VerifyRehearsal(spy_id=spy_id_1, spy_name="spy_1", payload=SpyCall(args=(), kwargs={})), VerifyRehearsal(spy_id=spy_id_2, spy_name="spy_2", payload=SpyCall(args=(), kwargs={})), ] calls = [ SpyEvent(spy_id=spy_id_1, spy_name="spy_1", payload=SpyCall(args=(), kwargs={})) ] decoy.when( spy_log.consume_verify_rehearsals( count=2, ignore_extra_args=False)).then_return(rehearsals) decoy.when(spy_log.get_calls_to_verify([spy_id_1, spy_id_2])).then_return(calls) subject.verify( "__rehearsal_1__", "__rehearsal_2__", times=None, ignore_extra_args=False, ) decoy.verify( verifier.verify(rehearsals=rehearsals, calls=calls, times=None))
def test_prop( decoy: Decoy, spy_log: SpyLog, subject: DecoyCore, ) -> None: """It should be able to create set and delete rehearsals.""" rehearsal = PropRehearsal( spy_id=1, spy_name="my_spy", payload=SpyPropAccess(prop_name="my_prop", access_type=PropAccessType.GET), ) decoy.when(spy_log.consume_prop_rehearsal()).then_return(rehearsal) result = subject.prop("__rehearsal__") result.set("hello") expected_set_event = SpyEvent( spy_id=1, spy_name="my_spy", payload=SpyPropAccess( prop_name="my_prop", access_type=PropAccessType.SET, value="hello", ), ) decoy.verify(spy_log.push(expected_set_event), times=1) result.delete() expected_delete_event = SpyEvent( spy_id=1, spy_name="my_spy", payload=SpyPropAccess(prop_name="my_prop", access_type=PropAccessType.DELETE), ) decoy.verify(spy_log.push(expected_delete_event), times=1)
def test_consume_verify_rehearsals_raises_error() -> None: """It should raise an error if the stack has too few members to pop a slice.""" subject = SpyLog() call_1 = SpyEvent(spy_id=1, spy_name="spy_1", payload=SpyCall(args=(), kwargs={})) subject.push(call_1) with pytest.raises(MissingRehearsalError): subject.consume_verify_rehearsals(count=2, ignore_extra_args=False)
def test_consume_verify_rehearsals_ignores_prop_gets() -> None: """It should be able to pop a slice off the stack, retaining order.""" subject = SpyLog() call_1 = SpyEvent(spy_id=101, spy_name="spy_1", payload=SpyCall(args=(1, ), kwargs={})) call_2 = SpyEvent( spy_id=101, spy_name="spy_1", payload=SpyPropAccess(prop_name="child", access_type=PropAccessType.GET), ) call_3 = SpyEvent( spy_id=102, spy_name="spy_1.child", payload=SpyCall(args=(2, ), kwargs={}), ) call_4 = SpyEvent( spy_id=102, spy_name="spy_1.child", payload=SpyPropAccess(prop_name="fizz", access_type=PropAccessType.DELETE), ) subject.push(call_1) subject.push(call_2) subject.push(call_3) subject.push(call_4) result = subject.consume_verify_rehearsals(count=3, ignore_extra_args=False) assert result == [ VerifyRehearsal( spy_id=101, spy_name="spy_1", payload=SpyCall(args=(1, ), kwargs={}), ), VerifyRehearsal( spy_id=102, spy_name="spy_1.child", payload=SpyCall(args=(2, ), kwargs={}), ), VerifyRehearsal( spy_id=102, spy_name="spy_1.child", payload=SpyPropAccess(prop_name="fizz", access_type=PropAccessType.DELETE), ), ]
def test_handle_call_with_raise( decoy: Decoy, spy_log: SpyLog, stub_store: StubStore, subject: CallHandler, ) -> None: """It raise a Stub's configured error.""" spy_call = SpyEvent(spy_id=42, spy_name="spy_name", payload=SpyCall(args=(), kwargs={})) behavior = StubBehavior(error=RuntimeError("oh no")) decoy.when(stub_store.get_by_call(spy_call)).then_return(behavior) with pytest.raises(RuntimeError, match="oh no"): subject.handle(spy_call) decoy.verify(spy_log.push(spy_call))
def test_handle_call_with_return( decoy: Decoy, spy_log: SpyLog, stub_store: StubStore, subject: CallHandler, ) -> None: """It return a Stub's configured return value.""" spy_call = SpyEvent(spy_id=42, spy_name="spy_name", payload=SpyCall(args=(), kwargs={})) behavior = StubBehavior(return_value="hello world") decoy.when(stub_store.get_by_call(spy_call)).then_return(behavior) result = subject.handle(spy_call) assert result == CallHandlerResult("hello world") decoy.verify(spy_log.push(spy_call))
def test_handle_call_with_context_enter( decoy: Decoy, spy_log: SpyLog, stub_store: StubStore, subject: CallHandler, ) -> None: """It return a Stub's configured context value.""" spy_call = SpyEvent(spy_id=42, spy_name="spy_name", payload=SpyCall(args=(), kwargs={})) behavior = StubBehavior(context_value="hello world") decoy.when(stub_store.get_by_call(spy_call)).then_return(behavior) with subject.handle(spy_call).value as result: # type: ignore[union-attr] assert result == "hello world" decoy.verify(spy_log.push(spy_call))
def test_handle_call_with_no_stubbing( decoy: Decoy, spy_log: SpyLog, stub_store: StubStore, subject: CallHandler, ) -> None: """It should noop and add the call to the stack if no stubbing is configured.""" spy_call = SpyEvent(spy_id=42, spy_name="spy_name", payload=SpyCall(args=(), kwargs={})) behavior = None decoy.when(stub_store.get_by_call(spy_call)).then_return(behavior) result = subject.handle(spy_call) assert result is None decoy.verify(spy_log.push(spy_call))
def test_when_ignore_extra_args( decoy: Decoy, spy_log: SpyLog, stub_store: StubStore, subject: DecoyCore, ) -> None: """It should be able to register a new stubbing.""" rehearsal = WhenRehearsal(spy_id=1, spy_name="my_spy", payload=SpyCall(args=(), kwargs={})) decoy.when(spy_log.consume_when_rehearsal( ignore_extra_args=True)).then_return(rehearsal) result = subject.when("__rehearsal__", ignore_extra_args=True) result.then_return("hello") decoy.verify( stub_store.add( rehearsal=rehearsal, behavior=StubBehavior(return_value="hello", once=False), ))
def test_when_then_raise( decoy: Decoy, spy_log: SpyLog, stub_store: StubStore, subject: DecoyCore, ) -> None: """It should add a raise behavior to a stub.""" rehearsal = WhenRehearsal(spy_id=1, spy_name="my_spy", payload=SpyCall(args=(), kwargs={})) decoy.when(spy_log.consume_when_rehearsal( ignore_extra_args=False)).then_return(rehearsal) error = RuntimeError("oh no") result = subject.when("__rehearsal__", ignore_extra_args=False) result.then_raise(error) decoy.verify( stub_store.add( rehearsal=rehearsal, behavior=StubBehavior(error=error), ))
def test_when_then_do( decoy: Decoy, spy_log: SpyLog, stub_store: StubStore, subject: DecoyCore, ) -> None: """It should add an action behavior to a stub.""" rehearsal = WhenRehearsal(spy_id=1, spy_name="my_spy", payload=SpyCall(args=(), kwargs={})) decoy.when(spy_log.consume_when_rehearsal( ignore_extra_args=False)).then_return(rehearsal) action = lambda: "hello world" # noqa: E731 result = subject.when("__rehearsal__", ignore_extra_args=False) result.then_do(action) decoy.verify( stub_store.add( rehearsal=rehearsal, behavior=StubBehavior(action=action), ))
def test_consume_prop_rehearsal_raises_empty_error() -> None: """It should raise an error a valid rehearsal event isn't found.""" subject = SpyLog() with pytest.raises(MissingRehearsalError): subject.consume_prop_rehearsal() event = SpyEvent( spy_id=42, spy_name="my_spy", payload=SpyPropAccess(prop_name="my_prop", access_type=PropAccessType.GET), ) subject.push(event) subject.consume_prop_rehearsal() with pytest.raises(MissingRehearsalError): subject.consume_prop_rehearsal() call = SpyEvent( spy_id=42, spy_name="my_spy", payload=SpyCall(args=(), kwargs={}), ) subject.push(call) with pytest.raises(MissingRehearsalError): subject.consume_prop_rehearsal() event = SpyEvent( spy_id=42, spy_name="my_spy", payload=SpyPropAccess(prop_name="my_prop", access_type=PropAccessType.DELETE), ) subject.push(event) with pytest.raises(MissingRehearsalError): subject.consume_prop_rehearsal()
def test_get_calls_to_verify() -> None: """It can get a list of calls made matching spy IDs of given rehearsals.""" subject = SpyLog() call_1 = SpyEvent( spy_id=101, spy_name="spy_1", payload=SpyCall(args=(1, ), kwargs={}), ) call_2 = SpyEvent( spy_id=101, spy_name="spy_1", payload=SpyCall(args=(2, ), kwargs={}), ) call_3 = SpyEvent( spy_id=202, spy_name="spy_2", payload=SpyCall(args=(1, ), kwargs={}), ) call_4 = SpyEvent( spy_id=101, spy_name="spy_1", payload=SpyCall(args=(1, ), kwargs={}), ) subject.push(call_1) subject.push(call_2) subject.consume_when_rehearsal(ignore_extra_args=False) subject.push(call_3) subject.push(call_4) result = subject.get_calls_to_verify([101]) assert result == [call_1, call_4] result = subject.get_calls_to_verify([101, 202]) assert result == [call_1, call_3, call_4] result = subject.get_calls_to_verify([303]) assert result == []
def test_clear() -> None: """It can clear all calls and rehearsals.""" subject = SpyLog() call_1 = SpyEvent(spy_id=101, spy_name="spy_1", payload=SpyCall(args=(), kwargs={})) call_2 = SpyEvent(spy_id=101, spy_name="spy_1", payload=SpyCall(args=(), kwargs={})) call_3 = SpyEvent(spy_id=202, spy_name="spy_2", payload=SpyCall(args=(), kwargs={})) subject.push(call_1) subject.consume_when_rehearsal(ignore_extra_args=False) subject.push(call_2) subject.push(call_3) subject.consume_when_rehearsal(ignore_extra_args=False) subject.clear() assert subject.get_all() == []