php - Correct unit testing -
i started using unit , functionality test project , because of have questions:
im working symfony php framework. , have doctrine ldap orm service.
furthermore have user repository (as service) depends on ldap orm service, logger , validation service.
now want write unit test adduser function of userrepo. internally call: getnewuidnumber, usertoentities, doesuserexist , getuserbyuid.
my question is: should mock these internal function test adduser function? against unit test idea (just test api).
or should mock ldap orm service, logger, , validation service, class calls internal functions? cause huge test function lot of mocking because have mock repositories internal repositories calls.
or should start symfony kernel , use servicecontainer use orm ldap service real test database. wouldn't functionally test , not unit test? heard bad have many dependencies in test. thought bad use whole servicecontainer.
adduser:
public function adduser(user $user) { $pbnlaccount = $this->usertoentities($user); if(!$this->doesuserexist($user)) { $pbnlaccount->setuidnumber($this->getnewuidnumber()); $this->ldapentitymanager->persist($pbnlaccount); $this->ldapentitymanager->flush(); } else { throw new useralreadyexistexception("the user ".$user->getuid()." exists."); } return $this->getuserbyuid($user->getuid()); }
for more code, internal functions: https://gist.github.com/nkpmedia/4a6ee55b6bb96e8af409debd98950678
thanks paul
first, rewrite method tiny bit, if may.
public function adduser(user $user) { if ($this->doesuserexist($user)) { throw new useralreadyexistexception("the user ".$user->getuid()." exists."); } // ... shortened brevity $pbnlaccount = $this->usertoentities($user); $this->ldapentitymanager->persist($pbnlaccount); }
the other relevant method is:
private function doesuserexist(user $user) { $users = $this->ldaprepository->findbyuid($user->getuid()); return count($users) === 1; }
immediately can see have 2 tests:
- we test method throws when user exists
- we test method persists pbnlaccount if user does not exist.
if not see why have these 2 tests, note there 2 possible "flows" in method: 1 block inside if statement executed, , 1 not executed.
lets tackle first one:
public function testadduserthrowswhenuserexistsalready() { $user = new user(); $user->setuid('123'); $ldaprepositorymock = $this->createmock(ldaprepository::class); $ldaprepositorymock ->method('findbyuid') ->expects($this->once()) ->with('123') ->willreturn(new pbnlaccount()); $userrepository = new userrepository($ldaprepositorymock); $this->expectexception(useralreadyexistexception::class); $userrepository->adduser($user); }
the second test left exercise reader :)
yes will have mocking in case. wil need mock ldaprepository , ldapentitymanager both in case.
note 1: code not runnable, since not know exact details of code base (and wrote off top of head), beside point. point want test exception.
note 2: rename function createnewpbnlaccountforuser(user $user)
longer, more descriptive of does.
note 3: not sure why returning $this->getuserbyuid()
since seems redundant (you have user right there), ommitting case.
Comments
Post a Comment