如何模拟 Guzzle 请求

huangapple go评论63阅读模式
英文:

How do I mock guzzle request

问题

如何模拟第三方API调用,该调用来自控制器。我在控制器中有以下代码行:

public function store(){
  $response = $request->post('http://thirdpaty.app/rmis/api/ebp/requests', [
                  "headers" => [
                      'Content-Type' => 'application/json',
                   ],
                "json" => [
                  "data"=>1
                   ]
            ]);
                $data = json_decode($response->getBody()->getContents());
                $token = $data->token;

         // 将该令牌保存到数据库

}

而在测试中,我正在执行以下操作:

$response = $this->post('/to-store-method');

我如何模拟API请求,以便在测试中不必调用第三方API请求。

目前我正在这样做:

if(app()->get('env') == 'testing'){
     $token = 123;
}else{
     // 在这里进行API调用
  }

是否有更好的替代方法来进行此测试?

英文:

How do I make a mock of third party api call . That is happening from controller . I have this line of code in controller .

public function store(){
  $response =    $request->post('http://thirdpaty.app/rmis/api/ebp/requests', [
                  "headers" => [
                      'Content-Type' => 'application/json',
                   ],
                "json" => [
                  "data"=>1
                   ]
            ]);
                $data = json_decode($response->getBody()->getContents());
                $token = $data->token;

         // Saving that token to database

}

And from the test I am doing

$response = $this->post('/to-store-method');

How do I mock the api request . So that in testing I don't have to call the third api request .

Right now I am doing

if(app()->get('env') == 'testing'){
     $token = 123;
}else{
     //Api call here
  }

Is there any better alternative of doing this test

答案1

得分: 1

你需要一种方法将一个模拟处理程序注入到你的控制器正在使用的 Guzzle Client 中。传统上,你可以通过将 Guzzle Client 通过构造函数传递或通过一些在代码中引用的服务来实现依赖注入,然后可以在幕后使用 Mockery 进行模拟。

之后,查看 Guzzle 文档以了解如何在 HTTP 客户端中模拟请求的方法:

http://docs.guzzlephp.org/en/stable/testing.html

你可以使用 MockHandler 来执行类似以下代码的操作,通过构建一组虚拟请求和响应:

// 创建一个模拟处理程序并排队两个响应。
$mock = new MockHandler([
    new Response(200, ['X-Foo' => 'Bar'], 'Hello, World'),
    new Response(202, ['Content-Length' => 0]),
    new RequestException('Error Communicating with Server', new Request('GET', 'test'))
]);

$handlerStack = HandlerStack::create($mock);
$client = new Client(['handler' => $handlerStack]);

// 第一个请求被第一个响应拦截。
$response = $client->request('GET', '/');
英文:

You'll need some way of injecting a mock handler into the Guzzle Client your controller is using. Traditionally, you'd either leverage dependency injection by passing the Guzzle Client via the constructor or through some referenced service in that code that you can mock (using Mockery) behind the scenes.

After that, check out the Guzzle documentation for a peak on how to mock requests in the HTTP Client:

http://docs.guzzlephp.org/en/stable/testing.html

You'd use a MockHandler to do something resembling the following code by building a stack of fake requests and responses.

// Create a mock and queue two responses.
$mock = new MockHandler([
    new Response(200, ['X-Foo' => 'Bar'], 'Hello, World'),
    new Response(202, ['Content-Length' => 0]),
    new RequestException('Error Communicating with Server', new Request('GET', 'test'))
]);

$handlerStack = HandlerStack::create($mock);
$client = new Client(['handler' => $handlerStack]);

// The first request is intercepted with the first response.
$response = $client->request('GET', '/');

答案2

得分: -2

实际上,模拟网络库是一个不好的做法。我建议的做法是通过httpService包装网络请求,然后模拟httpService以返回所需的响应。

public function store(){
  $response = httpService.postData();
  $data = json_decode($response->getBody()->getContents());
  $token = $data->token;

  // 将该令牌保存到数据库中

}

这样,您可以从httpService.postData函数中获得响应,并且您可以模拟postData而不是网络库。

英文:

Actually, it is a bad practice to mock the network libraries. What I would recommend is to wrap the network request by the httpService and mock the httpService instead to return the required response.

public function store(){
  $response =   httpService.postData();
                $data = json_decode($response->getBody()->getContents());
                $token = $data->token;

         // Saving that token to database

}

So, the you would get the response as return from the httpService.postData function and you can mock the postData instead of the network library.

huangapple
  • 本文由 发表于 2020年1月4日 01:25:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/59582778.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定