Laravel — Макет функции в модели

#laravel #mocking #phpunit #php-pest

Вопрос:

В моем приложении у меня есть служба, которая использует функцию, связанную с моделью.

Эта функция уже была протестирована (в ее модульном тесте), и в моем функциональном тесте мне просто нужно «использовать» ее выходное значение.

Поскольку эта функция «сложная», я бы высмеял ее значение, не беспокоясь о том, что делает функция. Таков сценарий:

Модель

 class MyModel {  public function calculateSomething()  {  // Implementation, already unit tested  // Here i put some "crazy" logic (this is not real :) )  if ($this-gt;field_a lt; 10 || $this-gt;field_b gt; 15) {  return true;  }   if ($this-gt;field_c !== null || $this-gt;field_e lt; 50) {  return false;  }   return true;  } }  

В моей службе мне не нужно воссоздавать эти условия, мне просто нужно сказать: «в этом тесте calculateSomething будет возвращено значение true», не важно, почему оно возвращается истинным

Обслуживание

 class MyService {  public function myMethod($id)  {  $models = MyModel::all();   foreach($models as $model) {  if ($model-gt;calculateSomething()) {  // Do domething here  } else {  // Do other stuff here  }  }  }   public function myMethodIsolated($model)  {  if ($model-gt;calculateSomething()) {  // Do domething here  } else {  // Do other stuff here  }  } }  

Обычно я издеваюсь над сервисом, но я никогда не издеваюсь над функцией внутри модели, можно ли издеваться над функцией, вычисляющей что-то ?

В моем примере я предоставил изолированную версию функции, называемую myMethodIsolated, в которой я передаю один экземпляр.

Комментарии:

1. Не могли бы вы добавить больше информации о том, что calculateSomething бы вы сделали? Я думаю, что «что-то не так», что-то кажется неправильным. Вы никогда не должны издеваться над a Model , так как это может скрыть/не запускать код, основанный на событиях или подобных… объясните подробнее, что делает этот метод, возможно, мы сможем инкапсулировать его еще больше.

2. это calculateSomething функция, которая проста в модульном тестировании, потому что я могу создать все условия для ее тестирования. В тесте функций мне не нужно заново создавать эти условия, но мне просто нужно использовать его возвращаемое значение для проверки логики.

3. Этот код не поддается проверке. Model::all вернет много экземпляров, и вы вызываете его в самой службе, что не дает вам возможности полностью или частично издеваться над ними. Лучшее, что вы можете сделать, — это использовать фабрику для обработки ваших данных таким образом, чтобы ваша функция возвращалась true , но это будет означать, что ваш код функции будет выполнен. В Laravel фабрики-это способ «имитировать» данные. Если вы все еще хотите издеваться над своими моделями, вам нужно будет изменить свою myMethod , чтобы использовать коллекцию моделей в качестве аргумента и издеваться над каждой моделью в своем тесте, прежде чем проходить его