#php #testing #testng-dataprovider #phpspec
#php #тестирование #testng-dataprovider #phpspec
Вопрос:
Я довольно новичок в тестировании Phpspec и я не знаю, как правильно протестировать несколько сценариев при преобразовании объекта в другую структуру ответа.
Мне нужно проверить, правильно ли рассчитана цена. Здесь у меня есть тест спецификации Transformer:
/**
* @dataProvider pricesProvider
*/
public function it_should_check_whether_the_prices_are_correct(
$priceWithoutVat,
$priceWithVat,
$vat,
Request $request,
Repository $repository
) {
$productIds = array(100001);
$result = array(
new Product(
'100001',
'MONSTER',
new Price(
$priceWithoutVat,
20,
'GBP',
null,
null
)
)
);
$expected = array(
array(
"productId" => "100001",
"brand" => "MONSTER",
"price" => array(
"amount" => $priceWithVat,
"vatAmount" => $vat,
"currencyCode" => "GBP",
"discountAmount" => (int)0
)
)
);
$repository->getResult(array(
Repository::FILTER_IDS => $productIds
))->willReturn($result);
$request->get('productIds')->willReturn(productIds);
/** @var SubjectSpec $transformedData */
$transformedData = $this->transform($request);
$transformedData->shouldEqual($expected);
}
public function pricesProvider()
{
return array(
array('123.456789', 14814, 2469),
array('60.00', 7200, 1200),
);
}
В моем классе Transformer у меня есть функция, которая форматирует данные в правильный формат:
public function transform(Request $request)
{
$productIds = $request->get('productIds');
$productsResult = $this->repository->getResult(array(
Repository::FILTER_IDS => $productIds
));
$products = array();
foreach ($productsResult as $product) {
$products[] = $this->formatData($product);
}
return $products;
}
/**
* @param Product $product
* @return array
*/
private function formatData(Product $product)
{
return array(
'productId' => $product->getId(),
'brand' => $product->getBrandName(),
'price' => array(
'amount' => (int)bcmul($product->getPrice()->getAmountWithTax(), '100'),
'vatAmount' => (int)bcmul($product->getPrice()->getTaxAmount(), '100'),
'currencyCode' => $product->getPrice()->getCurrencyCode(),
'discountAmount' => (int)bcmul($product->getPrice()->getDiscountAmount(), '100')
)
);
}
Проблема в том, что я получаю это сообщение об ошибке:
316 - it should check whether the prices are correct
warning: bcmul() expects parameter 1 to be string, object given in
/src/AppBundle/Database/Entity/Product/Price/Price.php line 49
Если я жестко запрограммирую эти значения, то тест будет зеленым. Однако я хочу протестировать цены и результаты varios, поэтому я решил использовать dataProvider
метод.
Но когда dataProvider
передается $amountWithoutTax
значение, это не строка, а PhpSpecWrapperCollaborator
класс, и из-за этого bcmul
происходит сбой.
Если я изменю $amountWithoutTax
значение на $priceWithoutVat->getWrappedObject()
, то DoublestdClassP97
класс будет передан, и из-за этого произойдет bcmul
сбой.
Как мне заставить это работать? Это какая-то банальность или я совершенно неправильно понял концепцию этого?
Я использую https://github.com/coduo/phpspec-data-provider-extension и в composer.json есть следующее:
"require-dev": {
"phpspec/phpspec": "2.5.8",
"coduo/phpspec-data-provider-extension": "^1.0"
}
Комментарии:
1. Что у вас есть, когда вы var_dump
$priceWithoutVat
,$priceWithVat
и$vat
в самом тесте? У вас есть номера?2. @DamianDziaduch Нет, они все
PhpSpecWrapperCollaborator
классные3. Похоже, проблема в пакете. Вам обязательно следует задать вопросы автору пакета / участникам через GitHub 🙂
Ответ №1:
Если getAmountWithTax()
в вашем formatData
методе возвращается экземпляр PhpSpecWrapperCollaborator
, это означает, что он возвращает макет Prophecy вместо фактического макета, то есть того, который вы получаете, вызывая reveal()
метод. Я не знаю, как выглядит ваш поставщик данных, но, похоже, вы издеваетесь над своими Price
объектами значений вместо того, чтобы создавать их реальные экземпляры, и $product->getPrice()
в вашем производственном коде возвращается объект неправильного типа.
Решением было бы либо создать реальный экземпляр объекта Price
value, который позже возвращается с помощью $product->getPrice()
with new
в поставщике данных, либо путем вызова reveal()
для этого экземпляра, вот так (предполагая, что $price
это макет объекта, который исходит из параметра с указанием типа):
$product->getPrice()->willReturn($price->reveal());