Chapters
29 Chapters
|
2:54:09
|
Login to bookmark this video
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.0, <7.4
Subscribe to download the code!Compatible PHP versions: ^7.0, <7.4
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
14.
Mocks: Control the Return Value
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
While the fundamentals of PHPUnit haven't changed, this tutorial *is* built on an older version of Symfony and PHPUnit.
What PHP libraries does this tutorial use?
// composer.json
{
"require": {
"php": "^7.0, <7.4",
"composer/package-versions-deprecated": "^1.11", // 1.11.99
"doctrine/doctrine-bundle": "^1.6", // 1.10.3
"doctrine/orm": "^2.5", // v2.7.2
"incenteev/composer-parameter-handler": "^2.0", // v2.1.2
"sensio/distribution-bundle": "^5.0.19", // v5.0.21
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.28
"symfony/monolog-bundle": "^3.1.0", // v3.1.2
"symfony/polyfill-apcu": "^1.0", // v1.6.0
"symfony/swiftmailer-bundle": "^2.3.10", // v2.6.7
"symfony/symfony": "3.3.*", // v3.3.13
"twig/twig": "^1.0||^2.0" // v2.4.4
},
"require-dev": {
"doctrine/data-fixtures": "^1.3", // 1.3.3
"doctrine/doctrine-fixtures-bundle": "^2.3", // v2.4.1
"liip/functional-test-bundle": "^1.8", // 1.8.0
"phpunit/phpunit": "^6.3", // 6.5.2
"sensio/generator-bundle": "^3.0", // v3.1.6
"symfony/phpunit-bridge": "^3.0" // v3.4.30
}
}
12 Comments
Hi,
I'm using Symfony 5 to follow along with this series.
I created a DinosaurFactory and using it like this in DinosaurFactoryTest
I added following code in setUp method
But the following doesn't work inside testItGrowsADinosaurFromASpecification
I also created a services_test.yaml and made the service public
I'm not sure if Factory can be used like that for this scenario. Could you please suggest how to inject mock dependency
Hey Jack,
Why are you injecting the mocked class into Symfony's container? Are you in a functional test? In this case, you only need to instantiate the DinosaurFactory manually in your tests and pass the mocked DinosaurLengthDeterminator object as an argument
Cheers!
oh okay. So I can't use the "DinosaurFactory::" and do "new DinosaurFactory()" with the mock service as an argument.
Thank you for the help
No errors are thrown btw. Just the tests are failing as the return value is random, not 20. So I assume the main service is loaded instead of the mock.
Hello, and thanks a lot for this tutorial
I am confused with: "Instead of simply testing the return value of the method, we're testing how the code is written internally... which in some ways, we should not care about: that's the business of the function. All we are supposed to care about is the return value. Writing stricter tests take more time, and will break accidentally more often."
Can you precise?
Or I can :)
"Instead of simply testing the return value of the method, we're
testing how the code is written internally..."
But I feel that with $this->assertSame(20, $dinosaur->getLength()); we are testing the return value here, the $dinosaur, don't we?
"which in some ways, we should not care about: that's the business of the function."
You mean the tested function, growFromSpecification, right?
Thanks!
Hey Francois,
As always, it depends :) Sometimes you can just make sure that the return value is exactly like we expected, but sometimes we need to make sure that the code internally works exactly as we want, for example, if we test user creation method, it should return a new User with some specified fields, but it also should send an email to the user. So, in this case we want to check the return value, but also make sure that the code inside of this method that sends the email was called, something like this. Agree, it requires more time to write those tests, it also may break more often, but that's the price to make sure that the internal code works properly too :)
I hope this helps!
Cheers!
Thank you Victor
Thanks for this general explanation, which is useful, but I was more concerned about the specific case which is mentionned in this video :
Here, in this specific example, I can only see a test of the return value, but the speaker says "Instead of simply testing the return value of the method, we're testing how the code is written internally".
This is what I don't understand, I can only see the test of a return result in these lines:
$dinosaur = $this->factory->growFromSpecification($spec);
$this->assertSame(20, $dinosaur->getLength())
What do I understand wrong?
Thanks
Hey Francois,
I believe in this spot the author means that's we're testing how the growFromSpecification() method works internally, i.e. with that asset that checks the return value we're making sure that the growFromSpecification() method created a proper object - it's happen internally in that method, and so we're kind of testing it internally subsequently, something like this. It's not only related to "$this->assertSame(20, $dinosaur->getLength());" but also to the above line as well: "$this->assertSame($expectedIsCarnivorous, $dinosaur->isCarnivorous(), 'Diets do not match');" - both are testing the result of the growFromSpecification() work, i.e. technically how it internally works.
I hope this helps!
Cheers!
Hum yes ok, I guess this exemple is a bit "in the middle", but I get the point anyway.
Thanks a lot!
Guys Can I ask you?
I created a mock of object
Set it on return value of repository class:
Then I create a handler and execute it:
Inside of handler i get the user and use username setter! :
But assertion don't pass. It still empty. How to check it then?
Thanks
Hey Sergei,
Because you mocked the User object - the method was called but it do nothing. PHPUnit just checked that the method you called is exist and that's it. First of all, usually, devs do not mock data objects like User in your case. Data objects are simple enough, so you can easily create real objects instead. Instead "$userStub = $this->createMock(User::class);" do "$user = new User();" and then change $userStub to $user further in the code and try again - it should work this way.
Or, if you want to continue using mocks for data objects, that I'd not recommend in this case, you can assert that "setUsername()" method was called once on that $userStub mocked object and that the argument passed was "John doe", e.g.:
Something like this.
Though your code inside handle() looks weird, as you're setting "John doe" username to every user? Is it ok? :)
Anyway, I hope this helps!
Cheers!
Thanks for the answer. It's ok. Just for example made it simple. But yeah looks weird xD
"Houston: no signs of life"
Start the conversation!