การใช้ PowerMockito.whenNew () ไม่ได้รับการเยาะเย้ยและเรียกวิธีการดั้งเดิม


104

ฉันมีรหัสแบบนี้ด้านล่าง:

Class A {
  public boolean myMethod(someargs) {
    MyQueryClass query = new MyQueryClass();
    Long id = query.getNextId();
    // some more code
  }
}
Class MyQueryClass     {
  ....
  public Long getNextId() {
    //lot of DB code, execute some DB query
    return id;
  }
}

ตอนนี้ฉันกำลังเขียนแบบทดสอบสำหรับ A.myMethod(someargs)เขียนสำหรับการทดสอบ ฉันต้องการข้ามวิธีการจริงquery.getNextId()และส่งคืนค่าต้นขั้วแทน MyQueryClassโดยทั่วไปฉันต้องการที่จะเยาะเย้ย

ดังนั้นในกรณีทดสอบของฉันฉันได้ใช้:

MyQueryClass query = PowerMockito.mock(MyQueryClass.class);
PowerMockito.whenNew(MyQueryClass.class).withNoArguments().thenReturn(query);
when(query.getNextId()).thenReturn(1000000L);

boolean b = A.getInstance().myMethod(args);

//asserts

ฉันใช้ @RunWith(PowerMockRunner.class)และ@PrepareForTest({MyQueryClass.class})อยู่ในช่วงเริ่มชั้นเรียนทดสอบของฉัน

แต่เมื่อฉันดีบักการทดสอบมันยังคงเรียกวิธีการจริง getNextId()ของMyQueryClassคลาส

ฉันขาดอะไรไปที่นี่? ใครช่วยได้บ้างเพราะฉันยังใหม่กับ Mockito และ PowerMockito

คำตอบ:


231

คุณต้องใส่คลาสที่ตัวสร้างถูกเรียกเข้าไปใน@PrepareForTestคำอธิบายประกอบแทนคลาสที่กำลังสร้าง - ดูการจำลองการสร้างอ็อบเจกต์ใหม่การก่อสร้างจำลองของวัตถุใหม่

ในกรณีของคุณ:

@PrepareForTest(MyQueryClass.class)

@PrepareForTest(A.class)

ทั่วไปมากขึ้น:

@PrepareForTest(NewInstanceClass.class)

@PrepareForTest(ClassThatCreatesTheNewInstance.class)


1
ขอบคุณมาก. ตอนนี้ใช้งานได้หลังจากรวมคลาสปัจจุบันเช่น A ใน @PrepareForTest
user3942446

2
ฉันใช้เวลาสักพักสำหรับเรื่องนี้ด้วย ขอบคุณ @TrueDub เนื่องจากข้อมูลอ้างอิงล้าสมัย ฉันเพิ่งอัปเดต github.com/jayway/powermock/wiki/MockConstructorมันบอกว่า: ใช้คำอธิบายประกอบ @PrepareForTest (ClassThatCreatesTheNewInstance.class) ที่ระดับคลาสของกรณีทดสอบ
Victor Choy

4
ฉันมีปัญหาเดียวกัน แต่วิธีนี้ใช้ไม่ได้สำหรับฉัน
dexter

3
โซลูชันนี้จะใช้ไม่ได้หากคุณใช้ eclemma สำหรับการครอบคลุมโค้ด การเพิ่มคลาสภายใต้การทดสอบไปยัง @PrepareForTest จะส่งผลให้คลาสนั้นครอบคลุม 0%
ACV

2
โซลูชันจะทำงาน - การทดสอบดำเนินการอย่างถูกต้อง เห็นได้ชัดว่า eclemma ไม่ได้พร้อมที่จะจัดการกับ PowerMockito ความครอบคลุมของรหัสไม่ได้เป็นส่วนหนึ่งของคำถามนี้
TrueDub

5

ดังที่ @TrueDub กล่าวถึงในการตอบกลับที่ยอมรับของเขาคุณต้องเพิ่มคลาสที่ตัวสร้างถูกเรียกไปที่@PrepareForTest.

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

วิกิ Powermockito

เราจะแทนที่ Javassist ด้วย ByteBuddy (# 727) และควรช่วยแก้ไขปัญหาเก่านี้ แต่ตอนนี้ไม่มีวิธีใช้ PowerMock กับ JaCoCo On-the-fly และไม่มีวิธีแก้ปัญหาเพื่อรับความครอบคลุมของรหัสใน IDE

ดังนั้นวิธีแก้ปัญหาที่นี่คือการ refactor รหัสจริงเพื่อใช้โรงงานแบบคงที่ซึ่งจะส่งคืนอินสแตนซ์ของคลาสนั้นจากนั้นจำลองแบบคงที่


เห็นด้วยกับความคิดเห็นของคุณ
Lathy

นั่นไม่ใช่ปัญหาใน Intellij
ACV

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

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