I'm trying to mock a third-party class called TwoFactorAuth, so in a test, I expect true to be returned to a method call. False is returned from the real class.
$this->mock(TwoFactorAuth::class, function (MockInterface $mock) {
$mock
->shouldReceive('verifyCode')
->andReturn(true);
});
$tfa = new TwoFactorAuth();
$valid = $tfa->verifyCode('667CNVRAUMQNNQN6', '123456');
dd($valid);//returns false
Ideally, I shouldn't have to change how the TwoFactorAuth class is being called, I've extracted this for posting here, but in my code the TwoFactorAuth class is used in a controller and not in the test directly.
But even with the above the mocked version isn't being used I don't think.
This version works but I had to change the implementation
$mock = Mockery::mock(TwoFactorAuth::class);
$mock->shouldReceive('verifyCode')->once()->andReturn(true);
// Bind the mock instance to the Laravel service container
$this->app->instance(TwoFactorAuth::class, $mock);
// Resolve the mocked instance from the container
$resolvedMock = app(TwoFactorAuth::class);
// Use the mocked instance to call verifyCode
$valid = $resolvedMock->verifyCode('667CNVRAUMQNNQN6', '123456');
dd($valid);//return true
In summary, the goal is to call a controller and mock a result so my test would call
$this->post(route('admin.2fa'), ['code' => '123456'])
->assertSessionHasNoErrors()
->assertRedirect(route('dashboard'))
The method I'm trying to test:
public function update(Request $request): Redirector|RedirectResponse
{
$request->validate([
'code' => 'required|string|min:6',
]);
$tfa = new TwoFactorAuth();
$valid = $tfa->verifyCode(auth()->user()->two_fa_secret_key, $request->input('code'));
if ($valid === false) {
return back()->withErrors('Code is invalid please try again.');
}
session()->forget('2fa-login');
return redirect(route('dashboard'));
}
source https://stackoverflow.com/questions/76893632/mocked-class-but-the-original-class-is-still-being-called
No comments:
Post a Comment