如何通过JSON从单元测试路由? [英] How to pass JSON to route from unit test?

查看:64
本文介绍了如何通过JSON从单元测试路由?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过模拟控制器期望的存储库来对Laravel 4 Controller进行单元测试.问题出在存储"功能上.当我对给定的控制器执行POST时,这是Laravel调用的函数.该函数被调用,但是期望 itemData 作为输入,但是我不知道该如何提供.这是我尝试过的:

I am unit testing my Laravel 4 Controller by mocking my repository that the controller expects. The problem is with the "store" function. This is the function that is called by Laravel when I do a POST to the given controller. The function gets called, but it is expected itemData as an input but I don't know how to provide that. Here is what I've tried:

ItemEntryController

class ItemEntryController extends BaseController
{
    protected $itemRepo;

    public function __construct(ItemEntryRepositoryInterface $itemRepo)
    {
        $this->itemRepo = $itemRepo;
    }

    public function store()
    {
        if(Input::has('itemData'))
        {
            $data = Input::get('itemData');

            return $this->itemRepo->createAndSave($data);
        }
    }
}

测试课程

<?php

use \Mockery as m;

class ItemEntryRouteAndControllerTest extends TestCase {

protected $testItemToStore = '{"test":12345}';

public function setUp()
{
    parent::setUp();
    $this->mock = $this->mock('Storage\ItemEntry\ItemEntryRepositoryInterface');
}

public function mock($class)
{
    $mock = m::mock($class);
    $this->app->instance($class, $mock);

    return $mock;
}

public function testItemStore()
{
    Input::replace($input = ['itemData' => $this->testItemToStore]);

    $this->mock
        ->shouldReceive('createAndSave')
        ->once()
        ->with($input);

    $this->call('POST', 'api/v1/tools/itementry/items');
}

推荐答案

嗯,您有一些选择.

您可能要遵循单元测试文档,该文档实际上具有 call()方法,您可以设置所有这些.这会引导应用程序,并会使用您的数据库等.

You may want to follow the unit testing docs, which actually has a call() method which allows you set all of this. This bootstraps the app and will use your databases, etc.

这比单元测试更像是集成测试,因为它使用了实际的类实现.

This is more of an integration test than unit test, as it uses your actual class implementations.

这实际上可能是更可取的,因为单元测试控制器 实际上没有多大意义(从理论上讲,它做的并不多,但是可以调用其他已经进行单元测试的类).但这涉及单元测试,集成测试,验收测试以及其中适用的所有细微差别.(阅读!)

This may actually be preferable, as Unit testing controllers may not actually make much sense (it doesn't do much, in theory, but call other already-unit-tested classes). But this gets into unit testing vs integration testing vs acceptance testing and all the nuances that apply therein. (Read up!)

如果您实际上实际上正在进行单元测试,则需要使控制器可以进行单元测试(ha!).(可能)意味着注入所有依赖项:

If you're actually looking to unit test, then you need to make your controller unit-testable (ha!). This (likely) means injecting all dependencies:

class ItemEntryController extends BaseController
{
    protected $itemRepo;

    // Not pictured here is actually making sure an instance of
    // Request is passed to this controller (via Service Provider or
    // IoC binding)
    public function __construct(ItemEntryRepositoryInterface $itemRepo, Request $input)
    {
        $this->itemRepo = $itemRepo;
        $this->request = $input;
    }

    public function store()
    {
        if($this->input->has('itemData'))
        {
            // Get() is actually a static method so we use
            // the Request's way of getting the $_GET/$_POST variables
            // see note below!
            $data = $this->input->input('itemData');

            return $this->itemRepo->createAndSave($data);
        }
    }
}

旁注: Input facade 实际上是带有额外静态方法 get()

因此,既然我们不再使用Input并注入Request对象,我们可以通过模拟Request对象来对该类进行单元测试.

So now that we aren't using Input any longer, and are injecting the Request object, we can unit test this class by mocking the Request object.

希望有帮助!

这篇关于如何通过JSON从单元测试路由?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆