I create my test to check data validation. Below I posted code from my phpunit ValidatorTest and Validator class. It worked fine without foreach loop. For start I get array which can have many arrays inside. Each array has to contain two keys: 'code' and 'tax_class_id'. My problem is that on second iteration my Mock - groupSearchResultsInterfaceMock doesn't set right data. Function checkByCodeIfGroupExists gets empty array although it should get ['General']. When I change in my dataProvider their order that array with 'General' code goes as first it's giving me the expectedError. I have to change mock return Values in two functions in each iteration. I used xdebug and the taxClassRepositoryInterfaceMock is changing them in the correct way. I tried to understand why it's happening but found nothing. I also tried to change some things in setUp but nothing changed.
protected $existingTaxClassesId = [1, 2, 3];
protected $existingCodeGroups = ['General', 'NOT LOGGED IN'];
public function fullyValidBothDataProvider()
{
return [
[
[
['code' => 'first_customer_group', 'tax_class_id' => 10],
['code' => 'General', 'tax_class_id' => 1],
]
]
];
}
/**
* @dataProvider fullyValidBothDataProvider
* @test
* @param array $validData
*/
public function passingValidationWhenTaxClassIdAndGroupCodeAreValidAndWhenTaxCodeExistsAndGroupCodeDoesNot(
array $validData
) {
foreach ($validData as $value) {
$this->taxClassRepositoryInterfaceMock->method('get')->willReturn($value['tax_class_id']);
$items = in_array($value['code'], $this->existingCodeGroups) ? [$value['code']] : [];
$this->groupSearchResultsInterfaceMock->method('getItems')->willReturn($items);
$this->assertTrue($this->validatorMock->validateData($validData));
}
}
/**
* Validates customer groups data
*
* @param array $data
* @return bool
* @throws GroupDataException when customer group data is incorrect
*/
public function validateData(array $data): bool
{
$taxClassIdKey = GroupInterface::TAX_CLASS_ID;
$groupCodeKey = GroupInterface::CODE;
if (empty($data)) {
throw new DataNotSetException(__('Data is empty.'));
} else {
foreach ($data as $group) {
if (!isset($group[$taxClassIdKey]) || !isset($group[$groupCodeKey]) || !is_int($group[$taxClassIdKey])) {
throw new GroupDataException(__('Invalid data format. Every group array must contain ' .
$taxClassIdKey . ' and integer ' . $groupCodeKey . '.'));
} elseif ($this->checkByCodeIfGroupExists($group[$groupCodeKey])) {
throw new CodeGroupException(__('Group code ' . $group[$groupCodeKey] . ' already exists.'));
} elseif (!$this->checkIfTaxClassIdExists($group[$taxClassIdKey])) {
throw new TaxClassException(__('Tax class id ' . $group[$taxClassIdKey] . ' does not exist.'));
}
}
}
return true;
}
/**
* Return true if given group code exist
*
* @param string $groupCode
* @return bool
*/
public function checkByCodeIfGroupExists(string $groupCode): bool
{
$filter = $this->filterBuilder
->setField('customer_group_code')
->setValue($groupCode)
->setConditionType('eq')
->create();
$this->searchCriteriaBuilder->addFilters([$filter]);
$searchCriteria = $this->searchCriteriaBuilder->create();
$result = $this->groupRepository->getList($searchCriteria);
$items = $result->getItems();
return !empty($items);
}
/**
* Test setup
*/
public function setUp()
{
//
$objectFactoryMock = $this->getMockBuilder('Magento\Framework\Api\ObjectFactory')
->disableOriginalConstructor()
->getMock();
$filterBuilderMock = $this->getMock('Magento\Framework\Api\FilterBuilder', ['setValue'], [$objectFactoryMock],
'');
$this->filterBuilderMock = $filterBuilderMock;
$this->filterBuilderMock->method('setValue')->willReturn($filterBuilderMock);
$this->groupSearchResultsInterfaceMock = $this->getMock('Magento\Customer\Api\Data\GroupSearchResultsInterface');
$this->filterGroupBuilderMock = $this->getMockBuilder('Magento\Framework\Api\Search\FilterGroupBuilder')
->setMethods(['setFilters'])
->disableOriginalConstructor()
->getMock();
$this->filterGroupBuilderMock->method('setFilters')->willReturn($this->filterGroupBuilderMock);
//
$searchCriteriaInterfaceMock = $this->getMock('Magento\Framework\Api\SearchCriteriaInterface');
$this->searchCriteriaBuilderMock = $this->getMockBuilder('Magento\Framework\Api\SearchCriteriaBuilder')
->setMethods(['create', 'addFilters'])
->disableOriginalConstructor()
->getMock();
$this->searchCriteriaBuilderMock->method('addFilters')->willReturn($this->searchCriteriaBuilderMock);
$this->searchCriteriaBuilderMock->method('create')->willReturn($searchCriteriaInterfaceMock);
$this->groupRepositoryInterfaceMock = $this->getMock('Magento\Customer\Api\GroupRepositoryInterface');
$this->groupRepositoryInterfaceMock->method('getList')->willReturn($this->groupSearchResultsInterfaceMock);
$taxClassRepositoryInterfaceMock = $this->getMock('Magento\Tax\Api\TaxClassRepositoryInterface');
//changing its get function in each loop iteration later
$this->taxClassRepositoryInterfaceMock = $taxClassRepositoryInterfaceMock;
//
$loggerMock = $this->getMock('Psr\Log\LoggerInterface');
$validatorMock = $this->getMockBuilder($this->className)
->setMethods(null)
->setConstructorArgs([
'groupRepository' => $this->groupRepositoryInterfaceMock,
'taxClassRepository' => $this->taxClassRepositoryInterfaceMock,
'searchCriteriaBuilder' => $this->searchCriteriaBuilderMock,
'filterBuilder' => $this->filterBuilderMock,
'logger' => $loggerMock
])->getMock();
$this->validatorMock = $validatorMock;
}