лучший способ издеваться над глобальным статическим методом

0

мое приложение имеет библиотеку журналов с подписью:

final class Logger {
  public static method debug($msg);
  public static method warn($msg);
  public static method error($msg);
}

класс, который я хочу проверить, другой глобальный статический помощник, используйте его как

final class TestMe {
  public static method TestThis(){
    Logger::debug('TestThis() called');
    doThings();
  }
}

Как протестировать класс TestMe, издеваясь над Logger и ожидая ожидаемых сообщений?

  • 0
    Если вы можете переписать или, по крайней мере, для дальнейшей разработки, тестируемость достигается с помощью статических экземпляров не статических классов. Вы должны быть в состоянии ввести Logger, и у этого регистратора не должно быть статических методов, чтобы его можно было смоделировать. В крайнем случае попробуйте github.com/Codeception/AspectMock
Теги:
unit-testing
testing
phpunit

2 ответа

2
Лучший ответ

Класс Logger не может быть изделен PHPUnit по нескольким причинам.

  1. Класс указан как final что означает, что он не может быть расширен. Когда PHPUnit создает макет объекта, он создает новый объект, который расширяет класс, который насмехается. final ключевое слово предотвращает расширение класса, поэтому макет не может быть создан.
  2. Методы, которые вы хотите заменить, называются статически. Вы не можете их заменить, потому что вызовы направляются в фактический класс. PHPUnit 5.3 имеет способ "насмешек" статических методов, но это только внутри класса, называемого статически. Он не заменяет вызовы извне класса.

http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/

У вас есть два варианта тестирования таких вещей:

  1. Увеличьте масштабы поведения, которое вы тестируете. Убедитесь, что все, что делает класс Logger выполняется. Это сделает любые тесты менее "единичными" тестами, но они инкапсулируют ожидаемое поведение и все еще могут быть полезны.
  2. Рефакторинг ваших обычаев для использования инъекции зависимостей, чтобы вы могли проходить в mockLogger, который не вызывает статические методы. Это может быть более болезненным, но в результате ваш код станет более гибким.
-3

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

Здесь подробно объясняется:

https://phpunit.de/manual/current/en/test-doubles.html

Вот небольшой пример, взятый с этой страницы:

<?php
require_once 'SomeClass.php';

class StubTest extends PHPUnit_Framework_TestCase
{
    public function testStub()
    {
        // Create a stub for the SomeClass class.
        $stub = $this->getMockBuilder('SomeClass')
                     ->getMock();

        // Configure the stub.
        $stub->method('doSomething')
             ->willReturn('foo');

        // Calling $stub->doSomething() will now return
        // 'foo'.
        $this->assertEquals('foo', $stub->doSomething());
    }
}
?>
  • 0
    когда я вызываю ->method() в макете для статического класса, он не может сказать, что такого метода нет.
  • 0
    только что заметил это в руководстве: Limitations Please note that final, private and static methods cannot be stubbed or mocked.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню