yii2: ActiveFixture does not delete actual data in unload() method
ActiveFixture unload does not call resetTable() in unload() and this causes trouble when you have dependant fixtures with foreign key constraints. As ActiveFixture tries to loadFixtures(), which calls resetTable() it fails as the dependant data is not deleted. The issue description is related with #5441
About this issue
- Original URL
- State: closed
- Created 10 years ago
- Comments: 41 (35 by maintainers)
Commits related to this issue
- Fixes #5442: Fixed problem on load fixture dependencies with database related tests — committed to yiisoft/yii2 by leandrogehlen 7 years ago
- update (#1) * Fixes #13945: Removed Courier New from error page fonts list since it looks bad on Linux (#13947) * Fixed phpdoc broken links to PHP manual pages [skip ci] * Fixes #10675: Added d... — committed to mixartemev/yii2 by mixartemev 7 years ago
Hi, If you want unload fixture in load function you should care about depends. I read documentation that says unload remove all fixture data.
Take a look at: https://github.com/yiisoft/yii2/blob/master/framework/test/FixtureTrait.php#L33 https://github.com/yiisoft/yii2/blob/master/framework/test/Fixture.php#L36
You should clean up this thing, because you implement a lot of ways to do the same thing.
And still it does not WORK! Do you want provide reliable solution OR NOT?
I do not know if you know what you talking about. Unload MUST remove data after test. If you want have a debug data you should archive it, like a html pages.
For example you can simple make a database DUMP if there is any fail or error.
@leandrogehlen This issue is from 2014. Still is not solved. And is not going to be solved soon. And untill this is not solved people are reading the documentation and trying to implement this function. Off course it is not working, and we think that we did something wrong in fact that documentation feeds us not correct information. Or it would be solved, but I doubt it would be soon, Or untill that moment documentation I guess should have some note information letting us to know, that this function is not prepared.
Hey guys I have a suggestion. I spent hours confusing why unload doesn’t work. Then I found this post. If you gonna consider that unload is useless, maybe then it would be better to edit documentation that this method is nor realized, on discussing.
It says in documentation that unload clears data, but in fact it doesn’t. It really confuses and lost energy thinking that I did wrong test.
Or I would edit documentation myself if u let me to prevent other developers from that confusing.
The
resetTable()workaround cited by @tom-- does not work for me.This is my mysql workaround and should be added to each fixture model that has some dependant table:
What do you think about adding one more field to Fixture (public $unloadFirst = [] or something like that) which will contain links to all the dependent fixtures. Using this field it will be not too complicated to build unloading mechanism actually clearing all the tables in proper order and without any foreign key violations.
We don’t need any hard changes in loading fixtures - just add check if we need to unload data in any dependent tables. And of course we could return resetTable() to unload() and be sure unloading will be performed in correct order.
For example, fixture OrdersFixture is dependent of UserFixture. In database schema we also have foreign key not allowing us to have Orders not belonging to any User. We could build these fixtures like that:
Case 1: We call $UserFixture->load(), it will check it’s own $unloadFirst array and perform unload with actual clearing data for all fixtures there - before calling $UserFixture->unload(). In this case - call $OrderFixture->unload() prior to any actual user data loading. So after this we’ll have data in users table and empty orders table.
Case 2: We call $OrderFixture->load(), it will check it’s own $depends, will call $UserFixture->load, which will do all the same as described in Case 1 (first unload orders, then load users). And after that we can load all orders data as expected - into already emptied table. Both fixtures loaded and no any problems with foreign key violations.
Can we enhance Fixture this simple way or I missed something? This also can be used to make more complex depedencies (inherited dependencies, multiple dependencies). I see the only one significant consequence - we need to make some kind of cross-linking between fixtures with such dependencies and it also can make difficult the tracking of fixtures loading/unloading order. But I don’t think it’s too complicated for developers who knows how to use foreign keys in their database. Those who don’t use foreign keys with restrictions, may continue to use $depends field only.
How the
unloadmethod don’t executeresetTable, after tests the tables will have records, in the next execution, theresetTablewill happens onloadmethod and the first command will be:if table
producthave fk we will have fk constraint exceptionAssume dependency: A depends on B which depends on C
Yes, I’m thinking perhaps we should move data deleting code back to
unload()and think of a way to enforceunload()is always called (or can be called later) even if the test quits in the middle somehow. Not quite sure yet.@leandrogehlen we’re using InitDbFixture it’s quite helpful in part of turning off foreign checks and removing it is definitely BC.
@Kolyunya what do you mean? We’re using fixtures with depedences and everything seems fine. @dynasource imho, saving and deleting data is not what I want to worry about during testing process. So maybe fixtures are not so comfortable to use, but definetely bring the write way to testing flow.