หน่วยทดสอบวิธีการโมฆะ


15

เพื่อแก้ไขข้อผิดพลาดในการประยุกต์ใช้ผมปรับเปลี่ยนวิธีการตั้งชื่อโดยการเพิ่มการเรียกร้องให้เป็นวิธีการที่มีอยู่ชื่อ postLogingetShoppingCart

รหัส

protected void postLogin() {
  getShoppingCart();
}

อย่างไรก็ตามฉันไม่แน่ใจว่าวิธีที่ดีที่สุดในการเขียนบททดสอบpostLoginคืออะไร

วิธีที่ 1

ใช้การตรวจสอบจาก Mockito เพียงตรวจสอบว่าวิธีการนั้นถูกเรียก

verify(mock).getShoppingCart();

วิธีที่ 2

ทดสอบผลข้างเคียงของการเรียกใช้เมธอดโดยเรียกค่าของตะกร้าสินค้าของผู้ใช้

AssertNotNull(user.getShoppingCart());

วิธีการหนึ่งดีกว่าวิธีอื่นหรือไม่?


1
สิ่งที่ทำให้การทดสอบง่ายต่อการเข้าใจและรักษาโค้ดให้สะอาด หากคุณไม่แน่ใจเกี่ยวกับการออกแบบการทดสอบCOULDนั้นก็เป็นสัญญาณว่าการออกแบบรหัสนั้นปิดอยู่ ให้แน่ใจว่าคุณจะถามคำถามเหล่านี้: " ทำไมไม่เพิ่มว่าการแก้ไขข้อผิดพลาดการเรียกวิธีนี้คือ? ขวาวิธีการแก้ไขข้อผิดพลาดนี้หรือไม่?"
Caleb

8
หากgetShoppingCart()วิธีการของคุณไม่มีผลข้างเคียงคุณไม่จำเป็นต้องทดสอบสิ่งที่เรียกว่า หากมันมีผลข้างเคียงคุณควรเปลี่ยนชื่อจริง ๆ เพราะgetXXX()วิธีการตามอัตภาพควรเป็น idempotent
จูลส์

@Jules getNextValue? บางคนอาจพูดว่า "อย่าเรียกมันว่าผู้ทะเยอทะยานเปลี่ยนชื่อเป็นnextValue" แต่ฉันเคยเห็นgetNextมาก่อน บางทีตัวอย่างที่ดีกว่าน่าจะเป็นวัตถุที่แสดงถึงอิเล็กตรอน สิ่งที่เกิดขึ้นเมื่อฉันโทรgetPosition? หรือแย่กว่านั้นgetPosition(); getVelocity();
Aaron

คำตอบ:


18

ฉันมักจะชอบวิธีที่ 2

ทำไม? เพราะคุณต้องการpostLoginเปลี่ยนสถานะของระบบของคุณ แต่วิธีการที่จะทำให้สำเร็จ (และวิธีการที่เรียกใช้ภายในสำหรับสิ่งนี้) เป็นเพียงรายละเอียดการใช้งานไม่มีสิ่งใดที่การทดสอบหน่วยของคุณควรตั้งสมมติฐานใด ๆ ดังนั้นให้ทำการทดสอบของคุณดีกว่าเพื่อตรวจสอบสถานะสุดท้าย


4

ฉันจะเปลี่ยน get ช็อปปิ้งคาร์ทเป็นบางอย่างเช่นเริ่มต้นช็อปปิ้งรถเข็นวัตถุประสงค์ของวิธีการนั้นชัดเจนสำหรับใครก็ตามที่อ่านโดยไม่จำเป็นต้องตรวจสอบว่าวิธีการใดและผลข้างเคียงเช่นนี้อาจทำให้เกิดพฤติกรรมที่น่าประหลาดใจสำหรับผู้ใช้

ถ้า getShoppingCart อยู่ในคลาสอื่นและมีการทดสอบหน่วยแล้วฉันจะใช้วิธีที่ 1 - ไม่จำเป็นต้องทดสอบอีกครั้งสิ่งที่ทดสอบแล้ว ในกรณีนี้เรามั่นใจว่า getShoppingCart จะทำงานได้อย่างถูกต้องและเราต้องการรับรองว่ามันถูกเรียกจาก postLogin ดังนั้นหากใครบางคนในอนาคตลบการโทรนี้การทดสอบจะล้มเหลว

หาก getShoppingCart เป็นวิธีส่วนตัวที่ไม่สามารถทดสอบได้ด้วยตัวเองฉันจะใช้วิธีที่ 2 เพื่อให้แน่ใจว่าเมื่อ postLogin ถูกเรียกว่าฟังก์ชันการทำงานที่ต้องการของ getShoppingCart จะดำเนินการตามที่คาดไว้


1

เมื่อทดสอบการเรียกใช้ฟังก์ชั่น (เป็นโมฆะหรือไม่) ที่มีผลข้างเคียงมันสมบูรณ์แบบที่สุดในการทดสอบว่าผลข้างเคียงไม่เพียงเกิดขึ้น แต่เพื่อตรวจสอบว่าผลข้างเคียง (เอาท์พุทระบบหรือการเปลี่ยนแปลงสถานะ) เป็นสิ่งที่ต้องการ


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

0

ฉันจะไม่พูดคุยเกี่ยวกับการออกแบบของคุณ แต่ในกรณีของคุณฉันจะไปหาแนวทางแรกเพราะการทดสอบหน่วยสำหรับการทดสอบวิธีการทางเทคนิคโดยไม่คำนึงถึงงานของพวกเขาในโดเมนนั่นคือวิธีการของคุณpostLogin? ในทางเทคนิคแล้วมันเรียกgetShoppingCardดังนั้นคุณต้องทดสอบที่เรียกจริง ๆgetShoppingCardฉันจะสร้างการทดสอบอีกครั้งgetShoppingCardเพื่อทดสอบว่ามันทำอะไรและถ้ามันมีผลข้างเคียงฉันจะตรวจสอบในการทดสอบใหม่นั้น


0

คุณมีข้อผิดพลาดใน postLogin ดังนั้นสิ่งแรกที่คุณควรทำคือสร้างการทดสอบหน่วยซึ่งเมื่อทำการเรียก postLogin โดยไม่มีชุดข้อมูลที่คาดไว้จะ "ล้มเหลว"

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

สิ่งนี้จะต้องมีการเปลี่ยนแปลงเล็กน้อยซึ่งลูกค้าต้องเรียก postLogin ในขณะนี้จำเป็นต้องส่งข้อมูลตะกร้าสินค้าด้วย สำหรับฉันแล้วตอนนี้คุณก็ยังคงเชื่อมโยงกัน การเชื่อมต่อนี้จะกระทำโดยผู้โทร

จากนั้นคุณไม่จำเป็นต้องทดสอบ getShoppingCart ภายใน postLogin เพราะวิธีการที่แท้จริงภายใต้การทดสอบคือ postLogin มันเป็นอันที่มีข้อผิดพลาดและอันเดียวที่ต้องมีการแก้ไขและการตรวจสอบที่เหมาะสม ด้วยการพึ่งพาการฉีดคุณจะสามารถทดสอบได้อย่างง่ายดายภายใต้เงื่อนไขที่แตกต่างกันและยืนยันว่าไม่มีข้อผิดพลาดถูกโยน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.