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

Add "set property" method to mock object? #1341

Closed
iwasherefirst2 opened this issue Nov 22, 2023 · 1 comment
Closed

Add "set property" method to mock object? #1341

iwasherefirst2 opened this issue Nov 22, 2023 · 1 comment
Assignees
Labels
Feature Request request a new feature Question looking for information

Comments

@iwasherefirst2
Copy link

Mockery Version

1.6.6

PHP Version

PHP 8.2

Issue Description

It is not possible to set properties to objects who have a __set() method, as this is always called instead on the mocked object. The only workaround that I know, is that one has to mock the methods inside the original class'es __set() method, see https://stackoverflow.com/a/26555404/2311074 which is not recommended https://docs.mockery.io/en/latest/reference/magic_methods.html

Steps to Reproduce

$mock = Mockery::mock('User');
$mock->roles = 2; // Calls __set() methods, which may lead to errors, like for any Laravel Eloquent object

Expected Behavior

Should change property of roles to 2

Actual Behavior

An exception is thrown instead

Exception or Error

BadMethodCallException: Method Mockery_0_User::setAttribute() does not exist on this mock object

Additional Information

Having a mockery set method like:

$mock = Mockery::mock('User');
$mock->addProperty('roles', 2);

would be great.

@iwasherefirst2 iwasherefirst2 added the triage needs to be triaged label Nov 22, 2023
@ghostwriter
Copy link
Member

Hey @iwasherefirst2,

Great question!

In general, Mockery does not support mocking any magic methods since these are generally not considered a public API.

So it’s recommend to mock virtual properties (those relying on __get() and __set()) as if they were actually declared on the class.

Mockery allows us to mock properties in several ways.

  • One way is that we can set a public property and its value on any mock object.
$mock = \Mockery::mock('User');
$mock->role = 2;
  • The second is that we can use the expectation methods set() and andSet() to set property values if that expectation is met.

Used with an expectation so that when a matching method is called, we can cause a mock object’s public property to be set to a specified value, by using andSet() or set():

$property = 'role';
$value = 2;

$mock = \Mockery::mock('User');

$mock->shouldReceive('setRole')->andSet($property, $value);
// or
$mock->shouldReceive('setRole')->set($property, $value);

https://docs.mockery.io/en/latest/reference/expectations.html#expectations-setting-public-properties

Note: set & andSet is not designed to be used with static properties.


Currently, there are no plans to introduce new methods for mocking virtual properties, those relying on __get() and __set() magic methods.

However, if you have any suggestions on how we can enhance this feature, we are open to reviewing and accepting pull requests.

@ghostwriter ghostwriter self-assigned this Nov 27, 2023
@ghostwriter ghostwriter added Feature Request request a new feature Question looking for information waiting-for-feedback Awaiting Reply issue or pull request requires a reply from the author. and removed triage needs to be triaged waiting-for-feedback labels Nov 27, 2023
@ghostwriter ghostwriter removed the Awaiting Reply issue or pull request requires a reply from the author. label Feb 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request request a new feature Question looking for information
Projects
None yet
Development

No branches or pull requests

2 participants