0

I have a basic check in PhpUnit where I am asserting if some object property is null using

$this->assertNull($object->property);

I would like to check if this property was never null in the life-span of this test method.

I read that PHPUnit has some never() method (see Table 8.1 Matchers in the Test Doubles section), but I was not able to find how I should use it.

More details added:

I am calling several methods in the test. Each of this methods can/will trigger observer. I would like to check if this property was potentially changed to null by some observer and then later set by other logic in the code. I am trying to capture some special scenario where object gets set to null and then later it repopulates again.

hakre
  • 193,403
  • 52
  • 435
  • 836
Bob
  • 8,392
  • 12
  • 55
  • 96
  • just read the docs, it shows the counter-parts: https://phpunit.readthedocs.io/en/9.5/assertions.html#assertnull - let me know if you still have a problem to locate it. – hakre Jul 15 '21 at 18:05
  • @hakre Not really sure how this differs from what I have already. I would like to check that this object property was never null during the processing that was done in the test. – Bob Jul 15 '21 at 18:22
  • asset*Not*Null() - as written in the link in my last comment a couple of minutes ago. maybe repeating it per quote helps to make it more bold: _"`assertNotNull()` is the inverse of this assertion and takes the same arguments."_ – hakre Jul 15 '21 at 18:24
  • @hakre this is not actually what I need. I am calling several methods in the test. Each of this methods can/will trigger observer. I would like to check if this property was potentially changed to null by some observer and then later set by other logic in the code. I am trying to capture some special scenario where object gets set to null and then later it repopulates again – Bob Jul 15 '21 at 18:26
  • ah, okay, that is indeed different. you would need an observer on the observer. does your observer has some self-observing or instrumentation capabilities? – hakre Jul 15 '21 at 18:29
  • I think it would be useful if you make that part of the problem more visible in your question already (as it is easy to misinterpret). And as you need to inverse where the expectation is asserted (changes to the objectproperty need to be tracked, or the events when such a change is send to the object), it would be good to know (e..g if you show a bit more of the test-setup) if `$object` can be of any (object) type. – hakre Jul 16 '21 at 10:24
  • And is the `never()` method you mention the one in [_Table 8.1 Matchers_ in the _Test Doubles_ section](https://phpunit.readthedocs.io/en/9.5/test-doubles.html?highlight=never()#test-doubles-mock-objects-tables-matchers)? – hakre Jul 16 '21 at 10:30
  • @hakre that is the method that I mentioned. I am not sure how to use it in this scenario. I will update the question, thanks! – Bob Jul 16 '21 at 10:33
  • I also already edited the question a bit, I hope it was fine. That `never()` can be used for an expectation on a _Mock_ but this works for methods only. If I get your question right, you're concerned about a (public?) property? And should the test immediately fail if any observer is changing the property to NULL or is the requirement to only test for a previous change at the end of the test? - And: Please add some code example of how the test looks like (compact it so it shows what you write in the text, if pseudo-code, write that it is pseudo-code). - ref: https://stackoverflow.com/q/1275413/ – hakre Jul 16 '21 at 10:40

1 Answers1

2

I think that firstly you should decide what exactly you want to test.

If you want to test the end result, then assertNull/assertNotNull will do.

But if you want to observe all changes of property value during script execution, then you should assert interactions, not state. There is no way to track property changes, but if you change the property accessibility to private/protected and add getter/setter, you could create a mock with some expectations about these getter/setter calls.

Update: For example you could extend you object with a so-called "spy" where override just one method - property setter - so that it will increment internal counter each time it is called. All other tested behavior will be left unchanged. Then run test against a spy instead of real object and assert the number of times the setter was called.

Ilia Yatsenko
  • 779
  • 4
  • 7
  • I'm not so sure if saying "there is no way to track property changes" is correct. But I'm with you that this is about interactions, not state. I wonder if a _Spy_ could not make use of magic setters (as outlined in https://stackoverflow.com/a/1275440/367456) as well. See as well _magic methods_ in PHP. But one should take care with magic as it is never fully understood and can ruin testing if suddenly things break and then you need to follow a whole trail of things hidden behind the curtain only to learn why the test failed. – hakre Jul 16 '21 at 13:23