Score:1

ฉันจะล้อเลียน \Drupal::httpClient() ได้อย่างไร

ธง jp

ฉันกำลังทดสอบไลบรารียูทิลิตี้ (ที่เราสร้างขึ้นเอง) ที่ทำการเรียกไปยัง REST API ภายนอกด้วย \Drupal::httpClient()

ดังนั้นฉันจึงมีคลาสไลบรารีพร้อมฟังก์ชันคงที่:

คลาส myUtils {
  ฟังก์ชันสแตติกสาธารณะ getFromApi($path)
  {
    ...
    $response = \Drupal::httpClient()->request( ... );
    ...
  }

...

}

และฉันต้องการเรียกสิ่งนั้นจากคลาสทดสอบ:

คลาส myUtilsTest ขยาย \Codeception\Test\Unit
{
  //ๆๆๆๆๆๆๆๆๆๆ...
  การทดสอบฟังก์ชั่นสาธารณะ GetFromApi()
  {
     //ร่ายเวทมนตร์เย้ยหยัน
     ...
     myUtils::getFromApi('/some/test/path');
     ...
  }
}

ฉันรู้ว่าฉันสามารถสร้าง \GuzzleHttp\Handler\MockHandler และตั้งค่าให้ส่งคืนสิ่งที่ฉันต้องการ แต่ฉันจะตั้งค่าให้ "เขียนทับ" การโทรได้อย่างไร \Drupal->httpClient()?

ฉันได้เห็นบางตัวอย่างที่ดูเหมือนจะถือว่าคุณมีอินสแตนซ์ของคลาสที่เป็นของตนเอง httpไคลเอนต์ สมาชิก และสิ่งนี้ถูกล้อเลียนได้ง่าย - แต่ในกรณีการใช้งานของฉัน ไม่มีเหตุผลเลยที่จะออกแบบโปรแกรมอรรถประโยชน์เช่นนั้น ดังนั้นฉันจะเยาะเย้ยได้อย่างไร ทั่วโลก \Drupal::httpClient() ในกรณีนี้?

ขอบคุณล่วงหน้าสำหรับการตอบกลับใด ๆ

Kevin avatar
in flag
ง่ายกว่าเพียงแค่รวมโมดูลทดสอบเท่านั้นที่มีบริการมิดเดิลแวร์เพื่อให้การตอบสนองสำหรับ API ภายในหรือภายนอก มิฉะนั้น คุณต้องจำลองคลาสที่ฉีดเข้าไปในบริการที่คุณกำลังทดสอบและจำลองแต่ละวิธีที่ใช้ในการนำไปใช้งานของคุณ
in flag
นี่เป็นสถานการณ์ที่ว่าทำไมคุณถึงต้องการการพึ่งพา ดังนั้น API ที่คุณพึ่งพานั้นเชื่อมโยงกับโค้ดของคุณอย่างหลวมๆ และสามารถจำลองและสลับระหว่างการทดสอบได้ เมื่อคุณเริ่มพึ่งพาสิ่งต่างๆ เช่น HTTP API, API ฐานข้อมูล, API เอนทิตี และเพื่อน คุณอาจต้องการพิจารณาวางเครื่องมือของคุณเป็นคลาสบริการแทน ฉันจะสงวนฟังก์ชันสแตติกเป็นตรรกะแบบสแตนด์อโลน (เช่น Html.php, Xss.php, UrlHelper.php ของคอร์ ฯลฯ เป็นตัวอย่างที่ดี)
jp flag
ตกลง ขอบคุณ จะพิจารณา! อย่างไรก็ตาม การเปลี่ยนสถาปัตยกรรมและการใช้งานที่ถูกต้องสมบูรณ์เพียงเพื่อจุดประสงค์ในการทดสอบเท่านั้น ทำให้ฉันผิดทางเล็กน้อย แต่ใช่ว่ามันอาจจะเป็นวิธี
Kevin avatar
in flag
การใช้คอนเทนเนอร์แบบสแตติกในชั้นเรียนไม่สนับสนุนด้วยเหตุผลหลายประการ ซึ่งเป็นหนึ่งในนั้น โชคดีที่การทำ DI นั้นไม่ยากเกินไป
jbarrio avatar
cn flag
ฉันเห็นด้วยกับ Patrick และพยายามสนับสนุนสิ่งนี้ในทางบวก ฉันขอบอกเลยว่าคุณเพิ่งพบสิ่งที่ควรปรับปรุงในการใช้งานปัจจุบันของคุณ และสาเหตุที่คุณประสบปัญหานี้อาจเป็นเพราะคุณไม่ได้นำโซลูชันของคุณไปใช้โดยคำนึงถึงแนวทาง T(B)DD ตั้งแต่เริ่มต้น ครั้งหน้าจะไม่เกิดเหตุการณ์แบบนี้กับคุณอีก :_)
jp flag
ฉันคิดว่าคุณไม่เป็นไร! ประสบการณ์การทดสอบของฉันเองส่วนใหญ่มาจาก Python ซึ่งเป็นไปได้ที่จะจำลองแบบไดนามิกมากขึ้น เพื่อให้การออกแบบโค้ดจริงไม่ต้องพิจารณาการทดสอบ (เนื่องจากคุณสามารถทดสอบได้ตลอดเวลา) แน่นอนว่านี่คือ Drupal และ PHP ไม่ใช่ Python และ Django ซึ่งประสบการณ์หลักของฉันอยู่ :-)
Score:3
ธง ph

การแปลงคลาสของคุณเพื่อใช้การพึ่งพาการฉีดจะมีลักษณะดังนี้:

ใช้ Drupal\Core\Plugin\ContainerFactoryPluginInterface;
ใช้ Symfony\Component\DependencyInjection\ContainerInterface;
ใช้ GuzzleHttp\Client

class myUtils ใช้ ContainerFactoryPluginInterface {

  /**
   * บริการ http
   *
   * @var \GuzzleHttp\ไคลเอนต์
   */
  ป้องกัน $httpClient;

  ฟังก์ชันสาธารณะขั้นสุดท้าย __construct (อาร์เรย์ $configuration, $plugin_id, $plugin_definition, Client $httpClient) {
    $this->httpClient = $httpClient;
    พาเรนต์::__construct($configuration, $plugin_id, $plugin_definition);
  }

  การสร้างฟังก์ชันสแตติกสาธารณะ (ContainerInterface $container, อาร์เรย์ $configuration, $plugin_id, $plugin_definition) {
    ส่งคืนค่าคงที่ใหม่ (
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('http_client')
    );
  }

  ฟังก์ชั่นสาธารณะ getFromApi($path)
  {
    ...
    $response = $this->httpClient->request( ... );
    ...
  }

...

}

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา