在这种情况下我该如何编写测试?

How can I write a test in this case?

P.S.: 起初我问如何模拟 Model::create,但我想做的是编写一个测试,当 try 发生错误时,它会正确地进入 catch。

感谢@matiaslauriti 的评论,我找到了更好的方法,所以我将把我的问题从如何模拟更改为如何编写测试。

详情请看答案部分和评论。

・・・・・・・・

我有这个代码。

class MyModel extends Model
{
    public static function addRecord()
    {
        //...

        try {
            DB::beginTransaction();

            foreach ($rows as $row) {
                self::create([
                    'name'         => $name,
                    'phone'         => '',
                ]);
            }

            DB::commit();
        } catch (\Exception $ex) {
            DB::rollback();

            throw($e);
        }

    }
}

这是我的测试 code.but 模拟 returns 一个错误,测试不起作用。

class MyModelTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        $this->my_model = new MyModel();

    }

    /**
     * @test
     */
    public function addRecord_error()
    {
        $mock = \Mockery::mock(MyModel::class)->makePartial();
        $mock->shouldReceive('create')
      ->once()
          ->andThrow(new \Exception());

        $this->app->bind(MyModel::class, function () use ($mock) {
            return $mock;
        });

     $my_model = app(MyModel::class);

        //run method
        $my_model->addRecord();  

        // ↑↑ This return error with 
              //BadMethodCallException:Static method 
              //Mockery_2_App_Models_MyModel::addRecord() does not exist on this mock object

        //try {
           //$my_model->addRecord();

        //} catch (\Exception $ex) {

          // $this->assertCount(0, MyModel::all());
        //}
    }
}

我想编写一个测试,如果尝试失败,它会进行捕获并调用回滚。

您的测试代码应如下所示:

use Exception;
use Mockery\Mockery;

class MyModelTest extends TestCase
{
    /**
     * @test
     */
    public function addRecord_error()
    {
        $mock = Mockery::mock(MyModel::class)->makePartial();
        $mock->shouldReceive('create')
      ->once()
          ->andThrow(new Exception);

        $my_model = app(MyModel::class);

        try {
            $my_model::addRecord();
        } catch (Exception $exception) {
           $this->assertCount(0, Model::all());
        }
    }
}

如果您在内部使用模型,则必须将模拟添加到 Service Container before app 辅助函数:

$this->app->bind(MyModel::class, function () use ($mock) {
    return $mock;
});

请记住,如果回滚,$this->assertCount(0, Model::all()); 应替换为您要测试的模型。因此,将 Model 替换为所需的 Model.

但是,那应该一直通过,因为你是第一次抛出错误 运行,所以你永远不会添加任何东西。所以assertCount应该总是pass的,删不删都是一样的。