# |
May 14th 2021, 19:13 |
etibor |
what is the best way to get the highest element in a group? i tried with select(['id'=>'MAX(id)'])->group(['document_id']) |
# |
May 14th 2021, 19:12 |
etibor |
hello everyone |
# |
May 14th 2021, 16:46 |
matthttam |
I'm off to lunch but i'll be back |
# |
May 14th 2021, 16:46 |
matthttam |
I'm just so confused on how to make something so simple but so complicated at the same time work.... |
# |
May 14th 2021, 16:45 |
matthttam |
Yea. I don't really care that the endpoint model in question is called or not. I just need it to not throw an error when loading the model and getting locations. I don't care to simulate what the API _should_ return... that is fine. Basically I wish I could do a fixture but without a database table.... one that pretends to give you a query and ultimately outputs an array I guess |
# |
May 14th 2021, 16:37 |
slackebot |
wrong data, that means that your test object wasn't (properly) invoked. |
# |
May 14th 2021, 16:37 |
ndm |
Both can be fine, mocks with expectations will give you more failure details so to speak, as they will check that your test actually used your test objects. Now if your test object returns data that is clearly different to what the real API would return, and you test for that specific data in the response, then the additional expectation of the test object being invoked would kinda be redundant, as you'd know that if you get the |
# |
May 14th 2021, 16:30 |
slackebot |
make those two things happen? |
# |
May 14th 2021, 16:30 |
matthttam |
All I know is that I want the code in the controller action: ```$this->loadModel('Freshservice.Locations', 'Endpoint'); $locations = $this->Locations->find('all')->toArray(); $this->set(compact('locations'));``` when ran by the test to work. So in my mind, I need the loadModel to not fail. And the $this->Locations->find('all')->toArray(); to create a predefined array of information. Would you recommend a mock or a stub to |
# |
May 14th 2021, 16:29 |
ndm |
As mentioned, it doesn't make much of a difference in your specific case, given how simple the code is. |
# |
May 14th 2021, 16:25 |
slackebot |
verifying behavior. |
# |
May 14th 2021, 16:25 |
ndm |
@matthttam It depends on where/how you use the mock. Generally a mock is ment to test whether it is interacted with in the way you expect it to, whether this is required/helpful/etc, depends. A stub will not cause a failure when the configured methods are not being invoked, or when they're invoked the wrong way. That information might be helpful to figure why things go wrong, even if your situation doesn't technically require |
# |
May 14th 2021, 15:52 |
matthttam |
Again, very new to this and I feel this is quite advanced. So my perceptions of how these are used could be very wrong. I've just been reading the PHPUnit docs |
# |
May 14th 2021, 15:51 |
matthttam |
I'll check that. But, it seems to me that Mock is meant to test the class itself sort of. But I am not testing that Locations->find() returns a query... I'm just trying to test that getting 'assets/test' loads properly. So, does it not make sense to just stub the "Endpoint" model to make that variable populate properly in the controller during the test? |
# |
May 14th 2021, 15:46 |
ndm |
Making your code shorter isn't a good reason, whether to use a stub or a mock should depend on what is appropriate/required from a purely technical point of view. `$this` in a closure will always refer to the outer scope. Again, check your error logs for information on what exactly is causing that 500 error. |
# |
May 14th 2021, 15:40 |
matthttam |
And, I can't use the EventManager::instance() for some reason... the code inside just throws a 500 error. I'm guessing because "this" isn't the test class anymore but rather the eventmanager class and I don't know how to fix this honestly |
# |
May 14th 2021, 15:39 |
slackebot |
presumably queryStub would have methods for returning an array The problem is I'm still stuck on: ```InvalidArgumentException: Unknown repository type "Endpoint". Make sure you register a type before trying to use it.``` |
# |
May 14th 2021, 15:39 |
matthttam |
I'm leaning to making a stub of each element to make this work and it may be because I don't completely understand _how_ to make a simple test run when I'm using this plugin.... I guess the "why" is so that _if_ I can make the code: ```$locator = \Cake\Datasource\FactoryLocator::get('Endpoint'); $locator->set('Freshservice.Locations', $locationsStub);``` work then I can just do a ->method('find')->willReturn($queryStub) Then |
# |
May 14th 2021, 15:36 |
ndm |
@matthttam The answer probably lies in the "_why_" you'd want to do that. It doesn't make much of a difference, stubs are just more lenient mocks, as they are ment to not define expectations. |
# |
May 14th 2021, 15:20 |
kevin.pfeifer |
@greenmanspirit hmm, seems strange. Got anything particular in your logs? It should work the same way from B => C if it already works from C => B |
# |
May 14th 2021, 15:17 |
greenmanspirit |
@kevin.pfeifer I have $this->belongsToMany('B'); in C and $this->belongsToMany('C'); in B |
# |
May 14th 2021, 15:16 |
matthttam |
@ndm What if.... What if I stubbed the LocationsEndpoint::class. Then mocked the query that is returned? |
# |
May 14th 2021, 15:13 |
kevin.pfeifer |
@greenmanspirit and you are sure you configured the HABTM Connection in your Table correctly on the B Model side? |
# |
May 14th 2021, 15:12 |
greenmanspirit |
@kevin.pfeifer Yes, that works just fine. |
# |
May 14th 2021, 15:10 |
slackebot |
building custom locators (if you can't use DI yet), then you could wrap things in custom services that have a cleaner, easier to mock API. As far as the error is concerned, check your error logs for more details (`/logs/`), 500 indicates that an exception was thrown. |
# |
May 14th 2021, 15:10 |
slackebot |
->getMockBuilder(\Muffin\Webservice\Datasource\Query::class) ->onlyMethods(['toArray']) ->getMock(); $queryMock ->expects($this->once()) ->method('toArray') ->willReturn([ 'some test data' ]); $locationsMock ->expects($this->once()) ->method('find') ->willReturn($queryMock);``` With that amount of mocking required, especially mocking 3rd party code, you may want to consider learning about |
# |
May 14th 2021, 15:10 |
ndm |
@matthttam Yes, expectations define what you expect with your mocks to happen, for example `find` being invoked and returning an object that you've defined, one that provides a `toArray()` method that returns your test data. That's PhpUnit basics, so I'd highly recommended that you make yourself familiar with it first: https://phpunit.readthedocs.io/en/9.5/test-doubles.html Quick and dirty example: ```$queryMock = $this |
# |
May 14th 2021, 15:08 |
kevin.pfeifer |
but when you delete an entry from model C does it remove the connection data between C and B for that? |
# |
May 14th 2021, 14:59 |
greenmanspirit |
delete when B is deleted. Any help will be appreciated. |
# |
May 14th 2021, 14:59 |
greenmanspirit |
hello, I am using CakePHP 4. I have three models (A, B, C). A hasMany B with saveStrategy = replace, B HABTM C. I am managing B's records using this method https://codethepixel.com/cakephp/cakephp-dynamic-input-and-saveassociated adjusted for CakePHP 4. The B records add and remove just fine but I cannot get entries in the join table for B and C to |
# |
May 14th 2021, 14:50 |
slackebot |
$this->assertResponseOk(); }``` |
# |
May 14th 2021, 14:50 |
slackebot |
$locationsMock = $this ->getMockBuilder(\Freshservice\Model\Endpoint\LocationsEndpoint::class) ->onlyMethods(['find', 'toArray']) ->getMock(); $locator = \Cake\Datasource\FactoryLocator::get('Endpoint'); $locator->set('Freshservice.Locations', $locationsMock); }); $this->login(); $this->get('assets/test'); |
# |
May 14th 2021, 14:50 |
matthttam |
``` public function testTest(): void { //$this->modelFactory('Endpoint', ['Muffin\Webservice\Model\EndpointRegistry', 'factory']); //$locations = $this->getMockForAbstractClass( // 'Freshservice\Webservice\LocationsWebservice', // array(), 'Locations', false // ); \Cake\Event\EventManager::instance()->on('Controller.initialize', function () { |
# |
May 14th 2021, 14:50 |
matthttam |
```Time: 2 seconds, Memory: 16.00 MB There was 1 failure: 1) App\Test\TestCase\Controller\AssetsControllerTest::testTest Failed asserting that 500 is between 200 and 204.``` |
# |
May 14th 2021, 14:50 |
slackebot |
further than I've gotten in my days of playing with this problem |
# |
May 14th 2021, 14:50 |
matthttam |
@ndm... so it is failing less hard now I think. I'm trying to understand what adding expectations would look like. Or what that does exactly... In my head, I expect: ```$locations = $this->Locations->find('all')->toArray();``` to return an array of data... Does this mean I need to add an expect to it where the method "find" returns an a resource or something? I'm just so confused.... TY for your help though so far this is |
# |
May 14th 2021, 14:45 |
matthttam |
Yea, no sandbox I don't think... that would be nice |
# |
May 14th 2021, 14:44 |
ndm |
Also check whether your api has a sandbox |
# |
May 14th 2021, 14:43 |
matthttam |
The API is quite extensive and subject to change. it would be way to difficult to simulate the whole thing honestly. I just want to mock the endpoints/webservices I'm using so that the controller can be tested. https://api.freshservice.com/v2/ |
# |
May 14th 2021, 14:42 |
ndm |
Alternatively consider using some kind of dummy server for your test environment that simulates the API. |
# |
May 14th 2021, 14:42 |
ndm |
Yes. |