Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE REQUEST] Mock actor objects for using testing #737

Closed
lor1113 opened this issue Oct 3, 2024 · 3 comments · Fixed by #750
Closed

[FEATURE REQUEST] Mock actor objects for using testing #737

lor1113 opened this issue Oct 3, 2024 · 3 comments · Fixed by #750
Assignees
Labels
kind/enhancement New feature or request stale Issue marked as stale by Dapr Bot

Comments

@lor1113
Copy link
Contributor

lor1113 commented Oct 3, 2024

I would like to suggest a mock/test actor object, implemented in the Python SDK, that would allow for easy and portable unit testing of various methods, without any dependency on the Dapr sidecar being up, or other processes being active. Essentially it would be an way to create an object that has all the methods an actor has, giving you the ability to call them in tests and check the result.

A code example of what I envisage the final result would look like would be (the specifics or names here do not particularly matter, it's just for demonstrating the idea):

testactor = TestActor(MyActor)
assert testactor.some_method(some_args) == what_you_expect

How I envisage this interacting with the various Actor features:

Actor activation / _on_activate()
This could either be automatically called on object instantiation, essentially replacing __init__ (just as Dapr does when instantiating a new actor instance) or be left as a method for the user to call manually . I'm not really sure what method I prefer. If you keep it as a separate method every time the mock object is used one would have to manually call the function (assuming it does some important setup) which is clutter, but on the other hand, it might be useful to keep it separate.

State storage:
This would be handled entirely locally, with each mock actor object holding its own state as a dict or other dict like object. Ideally this could be passed in at object creation, and read from the object directly. A code example of what a test would look like:

testactor = TestActor(MyActor, initstate=some_state)
testactor.method_that_changes_state(some_args)
assert testactor.state == what_you_expect

the ActorStateStore object used by the mock actor would only write to this temporary in memory dict-like store, which would only last the lifetime of each object and have no persistence - obviously, if you want to test actors activating or responding to requests in an environment with a populated state store, all you need to do is pass it in or set it.

Timers and reminders:
These should not have any of their actual functionality within the mock object, since it's simply outside the scope of what the mock actors are trying to do. You would simply unit test the methods they would call with the arguments they would use (and more complex end to end testing is outside of the scope of this proposal).

There does remain the question of testing adding and removing reminders / timers. For this, I propose that the mock actor register/unregister timer/reminder methods be overrwritten to simply point to an externally accessible list/dict of ActorReminderData and ActorTimerData instances which holds all the "active" timers/reminders for each actor object, which test code can then check and query to see if timers/reminders are being added and removed correctly (They can also be removed via TTL, of course, but again I would say that testing that functionality is outside of the scope of this). An code example of a test using this would look like:

testactor = TestActor(MyActor)
testactor.method_that_adds_reminder(some_args)
assert len(testactor.reminders) == 1
reminder = testactor.reminders[0]
assert reminder.name == what_you_expect
assert reminder.state== what_you_expect
. .  etc

Potential downsides and problems:
Obviously, the time and effort spent in creating this (I am personally willing to work on it, although it will take me a bit to get used to the SDK internals)
Development burden to potentially mirror future actor features if added
Inability to mirror "true" functionality for whatever reason (I can't think of one, but you never know, I suppose)

This is my first issue opened on Dapr and any open source project in general, so always open to see how it might be improved, fairly sure I read all the rules and contribution guidelines but maybe I missed something.

Release Note

RELEASE NOTE: ADD Mock actors for unit testing actor methods

@lor1113 lor1113 added the kind/enhancement New feature or request label Oct 3, 2024
@elena-kolevska
Copy link
Contributor

elena-kolevska commented Oct 9, 2024

I think this is a great idea @lor1113. Am I right in understanding that what we need would be an ActorProxy mock? We probably won't need mocking anything from the runtime, because we won't be going through that code path, correct?
@berndverst what do you think?

@lor1113
Copy link
Contributor Author

lor1113 commented Oct 27, 2024

/assign

This was referenced Oct 27, 2024
@dapr-bot
Copy link
Collaborator

This issue has been automatically marked as stale because it has not had activity in the last 60 days. It will be closed in the next 7 days unless it is tagged (pinned, good first issue, help wanted or triaged/resolved) or other activity occurs. Thank you for your contributions.

@dapr-bot dapr-bot added the stale Issue marked as stale by Dapr Bot label Dec 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/enhancement New feature or request stale Issue marked as stale by Dapr Bot
Projects
None yet
3 participants