Comment obtenir ScopeConfigInterface via le gestionnaire d'objets des tests unitaires dans magento 2?


8

J'essaie de lire une ligne de mon test unitaire à partir de core_config_table dans la base de données magento 2. Je sais que pour accomplir ce travail, j'ai lu ce lien . Je dois utiliser:

\Magento\Framework\App\Config\ScopeConfigInterface

par:

\Magento\Framework\TestFramework\Unit\Helper\ObjectManager

Voici mon code:

    protected function setUp()
{
    $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
    $this->scopeConfig = $objectManager->getObject('\Magento\Framework\App\Config\ScopeConfigInterface');
}

public function testgetImageCDNConfigValue()
{
    $this->scopeConfig->getValue($this->path, \Magento\Store\Model\ScopeInterface::SCOPE_STORE);
    if ($this->scopeConfig == null) {
        $this->assertFalse(true);
    } else {
        $this->assertTrue(true);
    }
}

Je peux obtenir tous les objets que je veux en utilisant testObject \Magento\Framework\TestFramework\Unit\Helper\ObjectManagermais chaque fois que je veux obtenir\Magento\Framework\App\Config\ScopeConfigInterface

Erreur fatale: impossible d'instancier l'interface Magento \ Framework \ App \ Config \ ScopeConf igInterface dans C: \ xampp \ htdocs \ magento \ vendor \ magento \ framework \ TestFramework \ Un it \ Helper \ ObjectManager.php sur la ligne 162


même problème ici ....
Michel Gokan

Réponses:


12

Je peux me tromper ici, mais je pense que pour les tests unitaires, vous n'avez pas à récupérer les valeurs de la base de données. Vous pouvez supposer que les implémentations de \Magento\Framework\App\Config\ScopeConfigInterfacesont testées et fonctionnent correctement. Vous n'avez qu'à tester votre méthode qui utilise getValuedepuis le ScopeConfigInterface.
Par exemple, si vous avez une méthode comme celle-ci:

public function getSomeConfigValue()
{
    return $this->scopeConfig->getValue('some/path/here', ScopeInterface::SCOPE_STORE)
}

vous devez tester cette méthode uniquement et non si la valeur de la base de données est ce dont vous avez besoin.
et vous pouvez tester cela comme ceci:

public function testGetSomeConfigValue()
{
    $dbValue = 'dummy_value_here';
    $scopeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class)
            ->disableOriginalConstructor()
            ->getMock();
    $scopeConfigMock->method('getValue')
            ->willReturn($dbValue);
    $objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
    $myClass = $objectManager->getObject(
        \Your\Class\Name\Here::class,
        [
             'scopeConfig' => $scopeConfigMock,
             ..., //your other mocked dependencies here
        ]
    );

    $this->assertEquals($dbValue, $myClass->getSomeConfigValue());
}

Selon le nombre de dépendances qui doivent être injectées dans le constructeur, il se peut que vous n'ayez même pas à utiliser le gestionnaire d'unités ObjectManager de test unitaire, mais vous pouvez simplement instancier la classe testée directement à l'aide new.

$myClass = new \Your\Class\Name\Here($scopeConfigMock);

C'est plus simple et en tant que tel préférable pour les tests unitaires. La seule raison d'utiliser le gestionnaire d'objet de test unitaire est si un grand nombre de dépendances rend la manipulation de chacune manuellement trop lourde.


merci pour votre excellente réponse. Considérez que je veux écrire un test dont le but est que lorsqu'une configuration de base est "True", les données de certains produits doivent être remplacées par X et lorsque leur "False", alors certaines données de produits doivent être remplacées par Y. Si j'ai besoin d'écrire un simuler pour tester cette fonctionnalité dans mon module, alors quel est l'intérêt des tests unitaires? Je veux tester mon module réel et réel, pas "une maquette" de sa fonctionnalité.
ali gh

dans ce cas, vous effectuez 2 tests. un pour quand la méthode getValueretourne vrai ->willReturn(true)et un pour quand getValueretourne faux. ->willReturn(false). De cette façon, vous testez votre module réel dans les deux cas, sans dépendre de ce que vous avez dans votre base de données.
Marius

1
@Marius est correct si vous écrivez un test unitaire, vous ne devriez pas parler directement à la base de données, mais vous devriez plutôt vous moquer de la portéeConfigInterface et supposer que l'état de configuration de la base de données est défini, lorsque vous commencez à vouloir obtenir des données de la base de données que vous commencez à passer aux tests d'intégration où vous pouvez ensuite invoquer la base de données réelle pour obtenir des données et effectuer des assertions sur celle-ci.
James Cowie

@Marius, j'ai fait ce que vous avez mentionné, mais lorsque j'affirme que je serai toujours vrai même si $ dbValue n'a pas la valeur réelle dans la base de données
ali gh

@aligh. C'était ça le point. Lisez le commentaire ci-dessus de James Cowie. Il est bien plus une autorité dans les tests unitaires (et toutes sortes de tests) que je ne le suis ou ne le serai jamais.
Marius

1

Je pense que vous devez utiliser la simulation pour cela, mais dans votre cas, cela nécessitera une refactorisation de votre module, en particulier le besoin d'une Configclasse liée à votre module.

Vous pouvez baser votre développement sur celui app/code/Magento/Braintree/Test/Unit/Gateway/Config/ConfigTest.phpqui implémente quelque chose comme ceci:

namespace Magento\Braintree\Test\Unit\Gateway\Config;

use Magento\Braintree\Gateway\Config\Config;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;

/**
 * Class ConfigTest
 */
class ConfigTest extends \PHPUnit_Framework_TestCase
{
    const METHOD_CODE = 'braintree';

    /**
     * @var Config
     */
    private $model;

    /**
     * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject
     */
    private $scopeConfigMock;

    protected function setUp()
    {
        $this->scopeConfigMock = $this->getMock(ScopeConfigInterface::class);

        $this->model = new Config($this->scopeConfigMock, self::METHOD_CODE);
    }

    /**
     * @param string $value
     * @param array $expected
     * @dataProvider getCountrySpecificCardTypeConfigDataProvider
     */
    public function testGetCountrySpecificCardTypeConfig($value, $expected)
    {
        $this->scopeConfigMock->expects(static::once())
            ->method('getValue')
            ->with($this->getPath(Config::KEY_COUNTRY_CREDIT_CARD), ScopeInterface::SCOPE_STORE, null)
            ->willReturn($value);

        static::assertEquals(
            $expected,
            $this->model->getCountrySpecificCardTypeConfig()
        );
    }

    /* skipped code */
}

Quel est le rôle de la fonction willReturn dans la méthode 'testGetCountrySpecificCardTypeConfig'?
ali gh
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.