How to mock internal calls with mockery












0















I try to mock a method of my service with Mockery lib. It works if I call that method from the test's context. But if I call it from another method (for example, it calls from another tested method) - it returns original data from implementation, but not from mock. What I'm doing wrong?
The example is below.



I added contract's because of my real implementation uses it. I don't think the problem is related to interfaces.



app/Contracts/TransactionsServiceContract.php



namespace AppContracts;

interface TransactionsServiceContract
{
public function getAllRequests(): array;

public function getRequests(array $necessaryFields): array;
}


app/Services/TransactionsService.php



namespace AppServices;

use AppContractsTransactionsServiceContract;

class TransactionsService implements TransactionsServiceContract
{

public function getAllRequests(): array
{
return [
'foo' => [
'metric' => 'foo',
],
'bar' => [
'metric' => 'bar',
],
'another' => [
'metric' => [
// Some fields
],
],
];
}

public function getRequests(array $necessaryFields): array
{
// dd($this->getAllRequests()); // -> for the test context it returns original value (above's one)
return collect($this->getAllRequests())->only($necessaryFields)
->map(function (array $metric) {
return $metric['formula'];
})
->toArray();
}
}


tests/Feature/TransactionsServiceTest.php



namespace TestsFeature;

use AppContractsTransactionsServiceContract;
use TestsTestCase;

class TransactionsServiceTest extends TestCase
{
/** @var TransactionsServiceContract */
private $_transactionsService;

public function setUp()
{
parent::setUp();
$requests = [
'test1' => [
'metric' => 'test 1',
],
'test2' => [
'metric' => 'test 2',
],
];
$this->_transactionsService = Mockery::mock(app()->make(TransactionsServiceContract::class))->makePartial();
$this->_transactionsService->shouldReceive('getAllRequests')->andReturn($requests);
}

public function testInternalCall()
{
$directCall = $this->_transactionsService->getAllRequests(); // returns array "requests" from the setUp method
dump($directCall);
$internalCall = $this->_transactionsService->getRequests(['test1']);
dd($internalCall); // if we call getAllRequests into getRequests, but not from test's context, we get original array from real implementation, but not test's mock
}
}


Versions of libs/frameworks:




  • Laravel: v5.7.19

  • PHPUnit: 7.5.1

  • Mockery: 1.2.0


Thanks for attention. Happy new year! :)










share|improve this question



























    0















    I try to mock a method of my service with Mockery lib. It works if I call that method from the test's context. But if I call it from another method (for example, it calls from another tested method) - it returns original data from implementation, but not from mock. What I'm doing wrong?
    The example is below.



    I added contract's because of my real implementation uses it. I don't think the problem is related to interfaces.



    app/Contracts/TransactionsServiceContract.php



    namespace AppContracts;

    interface TransactionsServiceContract
    {
    public function getAllRequests(): array;

    public function getRequests(array $necessaryFields): array;
    }


    app/Services/TransactionsService.php



    namespace AppServices;

    use AppContractsTransactionsServiceContract;

    class TransactionsService implements TransactionsServiceContract
    {

    public function getAllRequests(): array
    {
    return [
    'foo' => [
    'metric' => 'foo',
    ],
    'bar' => [
    'metric' => 'bar',
    ],
    'another' => [
    'metric' => [
    // Some fields
    ],
    ],
    ];
    }

    public function getRequests(array $necessaryFields): array
    {
    // dd($this->getAllRequests()); // -> for the test context it returns original value (above's one)
    return collect($this->getAllRequests())->only($necessaryFields)
    ->map(function (array $metric) {
    return $metric['formula'];
    })
    ->toArray();
    }
    }


    tests/Feature/TransactionsServiceTest.php



    namespace TestsFeature;

    use AppContractsTransactionsServiceContract;
    use TestsTestCase;

    class TransactionsServiceTest extends TestCase
    {
    /** @var TransactionsServiceContract */
    private $_transactionsService;

    public function setUp()
    {
    parent::setUp();
    $requests = [
    'test1' => [
    'metric' => 'test 1',
    ],
    'test2' => [
    'metric' => 'test 2',
    ],
    ];
    $this->_transactionsService = Mockery::mock(app()->make(TransactionsServiceContract::class))->makePartial();
    $this->_transactionsService->shouldReceive('getAllRequests')->andReturn($requests);
    }

    public function testInternalCall()
    {
    $directCall = $this->_transactionsService->getAllRequests(); // returns array "requests" from the setUp method
    dump($directCall);
    $internalCall = $this->_transactionsService->getRequests(['test1']);
    dd($internalCall); // if we call getAllRequests into getRequests, but not from test's context, we get original array from real implementation, but not test's mock
    }
    }


    Versions of libs/frameworks:




    • Laravel: v5.7.19

    • PHPUnit: 7.5.1

    • Mockery: 1.2.0


    Thanks for attention. Happy new year! :)










    share|improve this question

























      0












      0








      0








      I try to mock a method of my service with Mockery lib. It works if I call that method from the test's context. But if I call it from another method (for example, it calls from another tested method) - it returns original data from implementation, but not from mock. What I'm doing wrong?
      The example is below.



      I added contract's because of my real implementation uses it. I don't think the problem is related to interfaces.



      app/Contracts/TransactionsServiceContract.php



      namespace AppContracts;

      interface TransactionsServiceContract
      {
      public function getAllRequests(): array;

      public function getRequests(array $necessaryFields): array;
      }


      app/Services/TransactionsService.php



      namespace AppServices;

      use AppContractsTransactionsServiceContract;

      class TransactionsService implements TransactionsServiceContract
      {

      public function getAllRequests(): array
      {
      return [
      'foo' => [
      'metric' => 'foo',
      ],
      'bar' => [
      'metric' => 'bar',
      ],
      'another' => [
      'metric' => [
      // Some fields
      ],
      ],
      ];
      }

      public function getRequests(array $necessaryFields): array
      {
      // dd($this->getAllRequests()); // -> for the test context it returns original value (above's one)
      return collect($this->getAllRequests())->only($necessaryFields)
      ->map(function (array $metric) {
      return $metric['formula'];
      })
      ->toArray();
      }
      }


      tests/Feature/TransactionsServiceTest.php



      namespace TestsFeature;

      use AppContractsTransactionsServiceContract;
      use TestsTestCase;

      class TransactionsServiceTest extends TestCase
      {
      /** @var TransactionsServiceContract */
      private $_transactionsService;

      public function setUp()
      {
      parent::setUp();
      $requests = [
      'test1' => [
      'metric' => 'test 1',
      ],
      'test2' => [
      'metric' => 'test 2',
      ],
      ];
      $this->_transactionsService = Mockery::mock(app()->make(TransactionsServiceContract::class))->makePartial();
      $this->_transactionsService->shouldReceive('getAllRequests')->andReturn($requests);
      }

      public function testInternalCall()
      {
      $directCall = $this->_transactionsService->getAllRequests(); // returns array "requests" from the setUp method
      dump($directCall);
      $internalCall = $this->_transactionsService->getRequests(['test1']);
      dd($internalCall); // if we call getAllRequests into getRequests, but not from test's context, we get original array from real implementation, but not test's mock
      }
      }


      Versions of libs/frameworks:




      • Laravel: v5.7.19

      • PHPUnit: 7.5.1

      • Mockery: 1.2.0


      Thanks for attention. Happy new year! :)










      share|improve this question














      I try to mock a method of my service with Mockery lib. It works if I call that method from the test's context. But if I call it from another method (for example, it calls from another tested method) - it returns original data from implementation, but not from mock. What I'm doing wrong?
      The example is below.



      I added contract's because of my real implementation uses it. I don't think the problem is related to interfaces.



      app/Contracts/TransactionsServiceContract.php



      namespace AppContracts;

      interface TransactionsServiceContract
      {
      public function getAllRequests(): array;

      public function getRequests(array $necessaryFields): array;
      }


      app/Services/TransactionsService.php



      namespace AppServices;

      use AppContractsTransactionsServiceContract;

      class TransactionsService implements TransactionsServiceContract
      {

      public function getAllRequests(): array
      {
      return [
      'foo' => [
      'metric' => 'foo',
      ],
      'bar' => [
      'metric' => 'bar',
      ],
      'another' => [
      'metric' => [
      // Some fields
      ],
      ],
      ];
      }

      public function getRequests(array $necessaryFields): array
      {
      // dd($this->getAllRequests()); // -> for the test context it returns original value (above's one)
      return collect($this->getAllRequests())->only($necessaryFields)
      ->map(function (array $metric) {
      return $metric['formula'];
      })
      ->toArray();
      }
      }


      tests/Feature/TransactionsServiceTest.php



      namespace TestsFeature;

      use AppContractsTransactionsServiceContract;
      use TestsTestCase;

      class TransactionsServiceTest extends TestCase
      {
      /** @var TransactionsServiceContract */
      private $_transactionsService;

      public function setUp()
      {
      parent::setUp();
      $requests = [
      'test1' => [
      'metric' => 'test 1',
      ],
      'test2' => [
      'metric' => 'test 2',
      ],
      ];
      $this->_transactionsService = Mockery::mock(app()->make(TransactionsServiceContract::class))->makePartial();
      $this->_transactionsService->shouldReceive('getAllRequests')->andReturn($requests);
      }

      public function testInternalCall()
      {
      $directCall = $this->_transactionsService->getAllRequests(); // returns array "requests" from the setUp method
      dump($directCall);
      $internalCall = $this->_transactionsService->getRequests(['test1']);
      dd($internalCall); // if we call getAllRequests into getRequests, but not from test's context, we get original array from real implementation, but not test's mock
      }
      }


      Versions of libs/frameworks:




      • Laravel: v5.7.19

      • PHPUnit: 7.5.1

      • Mockery: 1.2.0


      Thanks for attention. Happy new year! :)







      laravel phpunit mockery






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 2 at 10:16









      Pavel SavushkinPavel Savushkin

      1




      1
























          1 Answer
          1






          active

          oldest

          votes


















          0














          When you call Mockery::mock(app()->make(TransactionsServiceContract::class))->makePartial(); in your setUp method, you're not really replacing the implementation existing in the app container. Laravel's container provides you with the bind method, to do that (the documentation for that). Besides you wouldn't replace an interface with a mock, as interfaces don't do anything per definition.

          So in fact you would do something like:



          app()->bind('AppTransactionsService', $mockedTransactionService);



          Note this will only work if your code gets an instance of the TransactionService by injection or resolving, not by calling new TransactionService.







          share|improve this answer
























          • thanks for your answer! In other words, I cannot mock methods of the class which will be returned from DI, right? So, I need to create an instance $mockedTransactionService (via new), mock methods and then bind it to my contract? Well, yes. It makes sense because the test file is created for testing exactly implementation. Thanks for your help!

            – Pavel Savushkin
            Jan 9 at 16:41













          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54004518%2fhow-to-mock-internal-calls-with-mockery%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          0














          When you call Mockery::mock(app()->make(TransactionsServiceContract::class))->makePartial(); in your setUp method, you're not really replacing the implementation existing in the app container. Laravel's container provides you with the bind method, to do that (the documentation for that). Besides you wouldn't replace an interface with a mock, as interfaces don't do anything per definition.

          So in fact you would do something like:



          app()->bind('AppTransactionsService', $mockedTransactionService);



          Note this will only work if your code gets an instance of the TransactionService by injection or resolving, not by calling new TransactionService.







          share|improve this answer
























          • thanks for your answer! In other words, I cannot mock methods of the class which will be returned from DI, right? So, I need to create an instance $mockedTransactionService (via new), mock methods and then bind it to my contract? Well, yes. It makes sense because the test file is created for testing exactly implementation. Thanks for your help!

            – Pavel Savushkin
            Jan 9 at 16:41


















          0














          When you call Mockery::mock(app()->make(TransactionsServiceContract::class))->makePartial(); in your setUp method, you're not really replacing the implementation existing in the app container. Laravel's container provides you with the bind method, to do that (the documentation for that). Besides you wouldn't replace an interface with a mock, as interfaces don't do anything per definition.

          So in fact you would do something like:



          app()->bind('AppTransactionsService', $mockedTransactionService);



          Note this will only work if your code gets an instance of the TransactionService by injection or resolving, not by calling new TransactionService.







          share|improve this answer
























          • thanks for your answer! In other words, I cannot mock methods of the class which will be returned from DI, right? So, I need to create an instance $mockedTransactionService (via new), mock methods and then bind it to my contract? Well, yes. It makes sense because the test file is created for testing exactly implementation. Thanks for your help!

            – Pavel Savushkin
            Jan 9 at 16:41
















          0












          0








          0







          When you call Mockery::mock(app()->make(TransactionsServiceContract::class))->makePartial(); in your setUp method, you're not really replacing the implementation existing in the app container. Laravel's container provides you with the bind method, to do that (the documentation for that). Besides you wouldn't replace an interface with a mock, as interfaces don't do anything per definition.

          So in fact you would do something like:



          app()->bind('AppTransactionsService', $mockedTransactionService);



          Note this will only work if your code gets an instance of the TransactionService by injection or resolving, not by calling new TransactionService.







          share|improve this answer













          When you call Mockery::mock(app()->make(TransactionsServiceContract::class))->makePartial(); in your setUp method, you're not really replacing the implementation existing in the app container. Laravel's container provides you with the bind method, to do that (the documentation for that). Besides you wouldn't replace an interface with a mock, as interfaces don't do anything per definition.

          So in fact you would do something like:



          app()->bind('AppTransactionsService', $mockedTransactionService);



          Note this will only work if your code gets an instance of the TransactionService by injection or resolving, not by calling new TransactionService.








          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jan 7 at 14:38









          BorisuBorisu

          520210




          520210













          • thanks for your answer! In other words, I cannot mock methods of the class which will be returned from DI, right? So, I need to create an instance $mockedTransactionService (via new), mock methods and then bind it to my contract? Well, yes. It makes sense because the test file is created for testing exactly implementation. Thanks for your help!

            – Pavel Savushkin
            Jan 9 at 16:41





















          • thanks for your answer! In other words, I cannot mock methods of the class which will be returned from DI, right? So, I need to create an instance $mockedTransactionService (via new), mock methods and then bind it to my contract? Well, yes. It makes sense because the test file is created for testing exactly implementation. Thanks for your help!

            – Pavel Savushkin
            Jan 9 at 16:41



















          thanks for your answer! In other words, I cannot mock methods of the class which will be returned from DI, right? So, I need to create an instance $mockedTransactionService (via new), mock methods and then bind it to my contract? Well, yes. It makes sense because the test file is created for testing exactly implementation. Thanks for your help!

          – Pavel Savushkin
          Jan 9 at 16:41







          thanks for your answer! In other words, I cannot mock methods of the class which will be returned from DI, right? So, I need to create an instance $mockedTransactionService (via new), mock methods and then bind it to my contract? Well, yes. It makes sense because the test file is created for testing exactly implementation. Thanks for your help!

          – Pavel Savushkin
          Jan 9 at 16:41






















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54004518%2fhow-to-mock-internal-calls-with-mockery%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Mossoró

          Error while reading .h5 file using the rhdf5 package in R

          Pushsharp Apns notification error: 'InvalidToken'