如何通过magento 2中的单元测试的对象管理器获取ScopeConfigInterface?


8

我正在尝试从magento 2数据库的core_config_table中读取我的单元测试中的一行。我已阅读此链接,知道完成这项工作 。我必须使用:

\Magento\Framework\App\Config\ScopeConfigInterface

通过:

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

这是我的代码:

    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);
    }
}

我可以使用testObject获得我想要的每个对象,\Magento\Framework\TestFramework\Unit\Helper\ObjectManager但是每当我想要获得时\Magento\Framework\App\Config\ScopeConfigInterface

致命错误:无法在第162行的C:\ xampp \ htdocs \ magento \ vendor \ magento \ framework \ TestFramework \ Un it \ Helper \ ObjectManager.php中实例化接口Magento \ Framework \ App \ Config \ ScopeConf igInterface


同样的问题在这里....
Michel Gokan

Answers:


12

我在这里可能是错的,但是我认为对于单元测试,您不必从数据库中检索值。您可以假定\Magento\Framework\App\Config\ScopeConfigInterface已测试的实现并且可以正常工作。您只需测试getValue从中使用的方法ScopeConfigInterface
例如,如果您有这样的方法:

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

您只需要测试该方法,而无需测试数据库中的值。
您可以这样测试:

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());
}

根据必须注入到构造函数中的依赖项的数量,您甚至可能不必使用单元测试ObjectManager,而可以直接使用实例化被测试的类new

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

这更简单,因此对于单元测试更可取。使用单元测试对象管理器的唯一原因是,如果大量的依赖项使手动模拟每个依赖项变得很麻烦。


感谢您的出色回答。考虑我想编写一个测试,其目的是当核心配置为“ True”时,某些产品的数据应替换为X,而当其“ False”时,某些产品的数据应替换为Y。如果我需要编写一个模拟在模块中测试该功能,那么单元测试的意义何在?我想测试我的实际模块和真实模块,而不是对其功能的“模拟”。
ali gh

在这种情况下,您需要进行2次测试。一种用于当方法getValue返回true时->willReturn(true),另一种用于when getValue返回false时。->willReturn(false)。这样,您就可以在两种情况下测试实际模块,而不取决于数据库中的内容。
Marius

1
@Marius是正确的,如果你正在写一个单元测试,那么你应该不会说话直接对数据库,而是你应该在scopeConfigInterface被嘲笑的,并假定数据库配置状态时,当你开始想从数据您将要开始进入集成测试的数据库,然后您可以在其中调用实际数据库以获取数据并对其进行声明。
詹姆斯·考威

@Marius我已经完成了您提到的内容,但是当我断言即使$ dbValue在数据库中没有实际值,我也将永远成真
ali gh

@aligh。这就是重点。阅读James Cowie的上述评论。在单元测试(以及所有类型的测试)方面,他比我现在或将来都拥有更大的权威。
Marius

1

我认为您需要为此使用模拟,但在您的情况下,它将需要对模块进行一些重构,尤其是需要Config与模块相关的类。

您可以基于app/code/Magento/Braintree/Test/Unit/Gateway/Config/ConfigTest.php实现类似以下内容的开发:

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 */
}

willReturn函数在“ testGetCountrySpecificCardTypeConfig”方法中的作用是什么?
ali gh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.