กรอบการจำลองที่ดีที่สุดสำหรับ Java คืออะไร [ปิด]


347

กรอบที่ดีที่สุดสำหรับการสร้างวัตถุจำลองใน Java คืออะไร ทำไม? ข้อดีและข้อเสียของแต่ละเฟรมเวิร์กคืออะไร

คำตอบ:


315

ผมเคยมีความสำเร็จที่ดีโดยใช้Mockito

เมื่อฉันลองเรียนรู้เกี่ยวกับ JMock และ EasyMock ฉันพบว่าช่วงการเรียนรู้นั้นค่อนข้างชัน (แม้ว่าอาจเป็นเพียงฉัน)

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

นี่คือตัวอย่าง (ย่อ) จากหน้าแรกของ Mockito:

import static org.mockito.Mockito.*;

List mockedList = mock(List.class);
mockedList.clear();
verify(mockedList).clear();

มันไม่ง่ายไปกว่านั้นอีกแล้ว

ข้อเสียที่สำคัญอย่างเดียวที่ฉันคิดได้ก็คือมันจะไม่เลียนแบบวิธีการคงที่


15
สวย. สำหรับวิธีการคงที่เพียงแค่รวม Mockito กับ JMockit และไม่มีการเรียนแบบ "ดั้งเดิม" เกินไปสำหรับคุณที่จะสามารถทดสอบได้
Epaga

6
ฉันรักเวลาที่คุณพยายามทำสิ่งที่คุณไม่ควรทำ (เช่นสร้าง mocks แบบอินไลน์) คุณจะได้คำอธิบายที่ชัดเจนมากเกี่ยวกับสิ่งที่คุณทำผิดในข้อความยกเว้น
ripper234

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

2
@MexicanHacker ทำไมคุณไม่ใช้กับ Android ล่ะ ฉันใช้มันตอนนี้กับ Robolectric
Ilkka

2
ฉันใช้ Mockito และรักมัน !! เอกสารที่ยอดเยี่ยมเช่นกัน (หาได้ยากมากในการค้นหาเอกสารคุณภาพนี้ผลงานที่ดีจากผู้เขียน) ซึ่งเป็นสิ่งสำคัญสำหรับเราที่จะใช้สิ่งต่าง ๆ โดยไม่ต้องขุดลงในกรอบของรหัส !!!
Renato

84

ฉันเป็นผู้สร้าง PowerMock ดังนั้นแน่นอนว่าฉันต้องแนะนำ! :-)

PowerMockขยายทั้ง EasyMock และ Mockito ด้วยความสามารถในการจำลองวิธีแบบคงที่วิธีสุดท้ายและแบบส่วนตัว การสนับสนุน EasyMock เสร็จสมบูรณ์ แต่ปลั๊กอิน Mockito ต้องการการทำงานเพิ่มเติม เรากำลังวางแผนที่จะเพิ่มการสนับสนุน JMock เช่นกัน

PowerMock ไม่ได้มีวัตถุประสงค์เพื่อแทนที่เฟรมเวิร์กอื่น แต่สามารถใช้ในสถานการณ์ที่ยุ่งยากได้เมื่อเฟรมเวิร์กอื่นไม่อนุญาตการเยาะเย้ย PowerMock ยังมีคุณสมบัติที่มีประโยชน์อื่น ๆ เช่นการยับยั้ง initializers คงที่และตัวสร้าง


Powermock เป็นสิ่งจำเป็นสำหรับหน่วยการทดสอบการใช้งาน Android ใช้พื้นเมืองของ Java บนเครื่องคอมพิวเตอร์โฮสต์ (หลีกเลี่ยงการใช้โปรแกรมจำลองช้า)
เจฟฟ์ Axelrod

@Jan ปัญหาเดียวคือ PowerMock เข้ากันไม่ได้เมื่อใช้ Robolectric แม้ว่า :-( ฉันต้องการทำ @RunWith (PowerMockRunner.class) และ @RunWith (RobolectricTestRunner.class)
Blundell

หลังจากใช้ PowerMock ในช่วงสองสามเดือนที่ผ่านมาฉันแนะนำอย่างเต็มที่!
cwash

PowerMock ยอดเยี่ยมจริงๆ ฉันชอบแบบซิงเกิลนิ่ง ๆ เพื่อเข้าถึงทุกอย่างและนี่ทำให้การทดสอบเป็นไปได้
Ian Macalinao

Caveat: บางสิ่งบางอย่างเช่นการเยาะเย้ยวิธีการขั้นสุดท้ายจะทำได้เฉพาะใน Powermock สำหรับ EasyMock และไม่ใช่สำหรับ Mockito เป็น gotcha เล็กน้อยเมื่อคุณไม่ได้ใช้มันบ่อย ฉันสงสัยว่าทำไมบางสิ่งบางอย่างไม่ทำงานฉันจึงรู้ว่ามันอยู่ในรายการใต้หัวข้อ Easymock ของ doco เท่านั้น
trafalmadorian

46

เว็บไซต์ของโครงการ JMockitมีความอุดมสมบูรณ์ของข้อมูลเปรียบเทียบสำหรับชุดเครื่องมือเยาะเย้ยปัจจุบัน

โดยเฉพาะให้ตรวจสอบเมทริกซ์การเปรียบเทียบคุณสมบัติซึ่งครอบคลุม EasyMock, jMock, Mockito, Unitils Mock, PowerMock และแน่นอน JMockit ฉันพยายามทำให้มันแม่นยำและทันสมัยมากที่สุด


1
ฉันประทับใจ JMockit มันมีช่วงการเรียนรู้ที่ชัน แต่มันมีเอกสารที่ดีมากสำหรับปีและมันสามารถเยาะเย้ยอะไรก็ได้ ฉันเริ่มต้นด้วย Mockito ซึ่งง่ายต่อการเรียนรู้ แต่ฉันพบปัญหาเป็นประจำซึ่งฉันไม่สามารถแก้ไขได้ ในขณะที่ฉันไม่สามารถจินตนาการได้ว่าอะไรเป็นไปไม่ได้กับ JMockit
Hontvári Levente

21

ฉันได้รับการมีความสำเร็จกับJMockit

มันค่อนข้างใหม่และค่อนข้างดิบและมีเอกสารน้อย มันใช้ASMเพื่อกำหนดคลาสไบต์ใหม่แบบไดนามิกดังนั้นจึงสามารถจำลองวิธีการทั้งหมดรวมถึงแบบคงที่ส่วนตัวส่วนสร้างและแบบคงที่เริ่มต้น ตัวอย่างเช่น:

import mockit.Mockit;

...
Mockit.redefineMethods(MyClassWithStaticInit.class,
                       MyReplacementClass.class);
...
class MyReplacementClass {
  public void $init() {...} // replace default constructor
  public static void $clinit{...} // replace static initializer
  public static void myStatic{...} // replace static method
  // etc...
}

มันมีอินเตอร์เฟซที่คาดหวังช่วยให้สถานการณ์การบันทึก / เล่นเช่นกัน

import mockit.Expectations;
import org.testng.annotations.Test;

public class ExpecationsTest {
  private MyClass obj;

  @Test
  public void testFoo() {
    new Expectations(true) {
      MyClass c;
      {
        obj = c;
        invokeReturning(c.getFoo("foo", false), "bas");
      }
    };

    assert "bas".equals(obj.getFoo("foo", false));

    Expectations.assertSatisfied();
  }

  public static class MyClass {
    public String getFoo(String str, boolean bool) {
      if (bool) {
        return "foo";
      } else {
        return "bar";
      }
    }
  }
}

ข้อเสียคือต้องใช้ Java 5/6


ใช่สามารถแนะนำสิ่งนี้ได้จริงๆ
Epaga

7
เพียงแค่การปรับปรุง: โครงการ JMockit ย้ายไปcode.google.com/p/jmockit มันมีการพัฒนามากตั้งแต่โพสต์นี้ (และยังคงมีการพัฒนา) และตอนนี้มีเอกสารมากมาย
Rogério

JMockit ได้ย้ายอีกครั้ง วางจำหน่ายแล้วที่ Github jmockit.github.io
Ravi Thapliyal

15

คุณสามารถดูการทดสอบโดยใช้ Groovy ใน Groovy คุณสามารถจำลองการเชื่อมต่อ Java ได้อย่างง่ายดายโดยใช้ตัวดำเนินการ 'as':

def request = [isUserInRole: { roleName -> roleName == "testRole"}] as HttpServletRequest 

นอกเหนือจากฟังก์ชั่นพื้นฐานนี้ Groovy ยังมีอีกมากที่ด้านหน้าเยาะเย้ยรวมถึงทรงพลังMockForและStubForคลาส

http://docs.codehaus.org/display/GROOVY/Groovy+Mocks


13

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

สิ่งที่ดีอีกอย่างคืออินเทอร์เฟซและคลาสการใช้งานได้รับการจัดการในลักษณะเดียวกันแตกต่างจาก EasyMock ซึ่งคุณยังต้องจำ (และตรวจสอบ) เพื่อใช้ EasyMock Class Extension

เมื่อไม่นานมานี้ฉันได้ดูที่JMockitอย่างรวดเร็วและในขณะที่รายการคุณสมบัติซักรีดนั้นค่อนข้างครอบคลุมฉันคิดว่าราคาของรหัสนี้เป็นรหัสที่อ่านง่ายและต้องเขียนเพิ่มเติม

สำหรับฉัน Mockito ได้รับความนิยมเป็นอย่างมากเขียนและอ่านได้ง่ายและจัดการกับสถานการณ์ส่วนใหญ่ที่โค้ดส่วนใหญ่ต้องการ การใช้ MockitoกับPowerMockเป็นทางเลือกของฉัน

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


1
+1 คำตอบนี้ต้องการ upvotes เพิ่มเติม หนึ่งควรแบ่งปันสิ่งที่พวกเขาชอบหรือไม่เกี่ยวกับกรอบ เพียงแค่ "ฉันใช้สิ่งนี้ .. และฉันชอบมัน!" เป็นหนึ่งในเหตุผลที่คำถามที่ดีดังกล่าวถูกปิดในดังนั้น
Ravi Thapliyal

11

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


1
ในคำถามของฉันฉันกำลังมองหาสิ่งที่คุณชอบและไม่ชอบเกี่ยวกับกรอบการเยาะเย้ยมากขึ้น ฉันสามารถหาเอกสารและอ่านทั้งหมดเกี่ยวกับมัน - ฉันต้องการที่จะรู้ว่าคนที่ใช้มันคิดว่ามัน
Josh Brown

EasyMock ใช้งานได้กับ Java 5 ขึ้นไปเท่านั้น!
matt b

8

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


6

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



4

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

ตัวอย่างเช่นคุณสมบัติต่อไปนี้ทดสอบเมธอด Math.sqrt เพื่อดูว่าสแควร์รูทของจำนวนบวกใด ๆ n กำลังสองเท่ากับ n

val propSqrt = forAll { (n: Int) => (n >= 0) ==> scala.Math.sqrt(n*n) == n }

เมื่อคุณโทรpropSqrt.check()ScalaCheck จะสร้างจำนวนเต็มเป็นร้อย ๆ และตรวจสอบคุณสมบัติของคุณสำหรับแต่ละรายการโดยอัตโนมัติเช่นกันเพื่อให้แน่ใจว่าเคสขอบได้รับการครอบคลุมอย่างดี

แม้ว่า ScalaCheck จะถูกเขียนใน Scala และต้องการ Scala Compiler มันเป็นเรื่องง่ายที่จะทดสอบโค้ด Java ด้วย เฟรมเวิร์ก Reductio ใน Functional Java เป็นการใช้งาน Java อย่างแท้จริงของแนวคิดเดียวกัน


3

Mockito ยังมีตัวเลือกของวิธีการขัดการจับคู่อาร์กิวเมนต์ (เช่น anyInt () และ anyString ()) เพื่อตรวจสอบจำนวนการร้องขอ (ครั้ง (3), atLeastOnce (), ไม่เคย ()) และอีกมากมายและอื่น ๆ

ฉันยังพบว่า Mockito นั้นเรียบง่ายและสะอาดเรียบง่ายและสะอาด

สิ่งหนึ่งที่ผมไม่ชอบเกี่ยวกับ Mockito คือการที่คุณไม่สามารถใช้วิธีการต้นขั้วแบบคงที่


คำตอบนี้ไม่ถูกต้อง คุณไม่ จำกัด เฉพาะอินเทอร์เฟซด้วย jMock คุณสามารถเลียนแบบคลาสที่เป็นรูปธรรมด้วย ClassImposteriser
เทฟลอน

คุณสามารถทำสิ่งเดียวกันกับ EasyMock ได้เช่นกัน
Cem Catikkas

ฉันลบความไม่ถูกต้องออกจากคำตอบของฉัน
Josh Brown

2

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


1

ฉันเริ่มใช้ mocks ผ่าน JMock แต่ในที่สุดก็เปลี่ยนไปใช้ EasyMock EasyMock เป็นเช่นนั้นง่ายขึ้นและให้ไวยากรณ์ที่รู้สึกเป็นธรรมชาติมากขึ้น ฉันไม่ได้เปลี่ยนตั้งแต่

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