首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >控制器单元测试(Symfony)

控制器单元测试(Symfony)
EN

Stack Overflow用户
提问于 2018-02-23 14:27:22
回答 2查看 1.1K关注 0票数 3

如何为此控制器创建单元测试?我知道如何发挥作用,但不知道单元测试.

代码语言:javascript
复制
class CatalogController extends Controller
{
    /**
     * @param Request $request
     * @return View
     */
    public function getAllAction(Request $request)
    {
        $name = $request->query->get('name');
        $result = $this->getDoctrine()->getRepository('AppBundle:Category')->findBy(array('name' => $name));
        if ($result === NULL) {
            return new View("Catalog not found", Response::HTTP_NOT_FOUND);
        }
        return new View($result,Response::HTTP_OK);
    }
    /**
     * @param $id
     * @return View|object
     */
    public function getAction($id)
    {
        $result = $this->getDoctrine()->getRepository('AppBundle:Category')->find($id);
        if (!$result instanceof Category) {
            return new View("ID: " . $id . " not found", Response::HTTP_NOT_FOUND);
        }
        return new View($result, Response::HTTP_OK);
    }
    /**
     * @param Request $request
     * @return View|Response
     */
    public function postAction(Request $request)
    {
        $serializer = $this->get('jms_serializer');
        $content = $request->getContent();
        $category = $serializer->deserialize($content,'AppBundle\Entity\Category','json');
        $errors = $this->get('validator')->validate($category);
        if (count($errors) > 0) {
            return new View("NAME LENGTH MUST BE >4",Response::HTTP_BAD_REQUEST);
        } else {
            $em = $this->getDoctrine()->getManager();
            $em->persist($category);
            $em->flush();
            return new View($category, Response::HTTP_OK);
        }}}

.........................................................................................................................

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-23 15:25:25

有一个老笑话,开头是“你怎么从大象身上下来?”最后是“你不,你从鸭子身上下来”。还是让我崩溃了。

关键是,如果您保持您的控制器操作苗条,那么您可能根本不需要对它们进行单元测试。当然,100%的代码覆盖率执行者将不同意这一点。

但是,如果您决心测试它们,那么您将需要进行一些严肃的重构,以保持您自己的理智。让我们看看您的getAllAction:

代码语言:javascript
复制
public function getAllAction(Request $request)
{
    $name = $request->query->get('name');

因此,您需要模拟一个请求对象,然后模拟一个包对象,然后添加一个测试,以查看get是否使用名称的参数被调用。充其量是痛苦。但是,Symfony实际上可以自动注入请求参数,因此:

代码语言:javascript
复制
public function getAllAction(string $name)
{

这就是你所需要的。更少的代码。很容易测试。有什么不喜欢的?

代码语言:javascript
复制
    $result = $this->getDoctrine()->getRepository('AppBundle:Category')->findBy(array('name' => $name));

现在这可能是一个真正的问题。如果您查看getDoctrine代码,您将看到它需要一个容器,该容器包含一个原则实体管理器注册表类,而后者又包含一个实体管理器,该实体管理器随后保存存储库。您真的想要模拟所有这些对象并将它们串在一起吗?您将花费更多的时间调试测试,而不是实际的代码。更重要的是,您的代码将不再在SF4中工作,因为它已经脱离了服务定位器模式。

幸运的是,使用动作注入可以很容易地修复:

代码语言:javascript
复制
public function getAllAction(string $name, CategoryRepository $categoryRepository)

您需要做一些研究来了解如何将存储库定义为服务,但这并不难,而且测试也相当容易。再一次,我们去掉了一行相当讨厌的代码。

现在这有点有趣了:

代码语言:javascript
复制
return new View("Catalog not found", Response::HTTP_NOT_FOUND);

对于单元测试,我们当然对测试View类本身没有兴趣。相反,我们想知道的是,视图是否使用了适当的参数来构造。不容易拦截新的行动。

相反,我们可以定义并注入一个ViewFactory

代码语言:javascript
复制
class ViewFactory
    public create($data,$status)
        return new View($data,$status)

因此,现在可以很容易地模拟视图工厂并测试create方法。更重要的是,控制器代码与View类没有太大的联系。

因此,如果您真的觉得需要对这些操作进行单元测试,那么就卷起袖子开始重构。我可以补充一点,在Symfony中查看新的自动测试功能也是个好主意。

票数 5
EN

Stack Overflow用户

发布于 2018-02-23 14:39:56

如果要单独测试PHP类和单元测试,则应该注入类中使用的所有服务。

作为起点:

代码语言:javascript
复制
    /** @test */
public function it_should_return_a_view(){

    $controller = new CatalogController();

    $result = $controller->getAllAction($mockedRequest, $mockedRepository);

    $this->assertInstanceOf(View::class, $result);
}

您需要模拟请求和存储库,这只有在将其注入方法或类的构造器注入时才有可能。

我希望这对您的单元测试方式有所帮助。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48950055

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档