KaiSassnowski's avatar

Model Relationship not getting updated in Behat test

I'm using Laravel 5.2 together with Behat. In several projects I was faced with the problem, that when I was trying to update a model or a resource within the test and then try to check to view to see if the changes actually took place, they seemingly never did. Note that all of this works as intended in the browser. It's just Behat that's acting up.

Let me give you an example. I have the following Scenario

  Scenario: Editing profile
    Given I am a User
    And I visit the profile edit page
    And I edit my profile
    Then I should see my updated profile

So I edit my profile, hit submit and then I should see my changed profile, right? The problem is, that in the returned response none of the fields actually changed. It's still the same way it was before I tried to edit. I printed the response to the console and checked the Html manually. No changes at all. Here's what my controller is doing when I update the profile:

 public function update()
 {
        $user = $this->users->currentUser();

        $profile = $this->profiles->findByField('user_id', $user->id)[0];

        $this->profiles->update(request()->input(), $profile->id);

        return redirect()->route('users.own-profile');
}

Note: I'm using the repository pattern here but I've had the exact same problem in another project where I'm just using the facades directly in the controller.

Now here's what I noticed. Look at my code that returns the actual profile page (not the edit page):

public function showOwn()
{
    $user = $this->users->currentUser();

    return view('user.profile', ['user' => $user, 'ownProfile' => true]);
}

$this->users->currentUser() simply calls auth()->user() in the background. Now the interesting thing is, that the user profile is actually a separate model which I'm accessing through $user->profile inside the views. When I do var_dump($user->profile->toArray()) in the above function, I can see that it actually still is the old, not-updated profile. HOWEVER when I do this

var_dump(UserProfile::where('user_id', $user->id)->first()->toArray());

I actually get the updated profile. I'm not sure what exactly is happening but it looks like the relationship does not get refetched. I can actually make the test pass if I change the above function to

public function showOwn()
{
    $user = $this->users->currentUser();

    // fetching the profile by hand
    $profile = $this->profiles->findByField('user_id', $user->id)[0];

    // and then pass it to the view and use it directly instead of $user->profile
    return view('user.profile', ['user' => $user, 'profile' => $profile, 'ownProfile' => true]);
}

Now naturally I don't want to be doing this throughout my code just to make my Behat tests pass. If anyone has had a similar problem and/or knows of a solution to this problem I would greatly appreciate it.

Regards Kai

0 likes
3 replies
fatihict's avatar

Hi,

Eloquent does a few smart things with caching, so it doesn't fetches a fresh copy of a model all the time you reference it. However, if you do wish for such behavior you can make a call to the fresh() method.

KaiSassnowski's avatar

But I would have to do that in my implementation code, not my test code right? I don't really want to alter the implementation to deal with a quirk that only Behat seems to have.

fatihict's avatar

Hello,

I think you need to get a fresh copy of the object you are retrieving here in the implementation of this method: Then I should see my updated profile. I can not say for certain, because i can't see your code :)

Please or to participate in this conversation.