เมื่อฉันเรียกใช้การทดสอบ mockito เกิดข้อยกเว้น WrongTypeOfReturnValue


96

รายละเอียดข้อผิดพลาด:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
Boolean cannot be returned by updateItemAttributesByJuId()
updateItemAttributesByJuId() should return ResultRich
This exception might occur in wrongly written multi-threaded tests.
Please refer to Mockito FAQ on limitations of concurrency testing.

รหัสของฉัน:

@InjectMocks
protected ItemArrangeManager arrangeManagerSpy = spy(new ItemArrangeManagerImpl());
@Mock
protected JuItemWriteService juItemWriteService;

when(arrangeManagerSpy
    .updateItemAttributes(mapCaptor.capture(), eq(juId), eq(itemTO.getSellerId())))
    .thenReturn(false);

ในขณะที่คุณสามารถดูฉันโทรwhenบนupdateItemAttributes(ซึ่งไม่กลับboolean) updateItemAttributesByJuIdไม่ได้อยู่ใน

  1. เหตุใด Mockito จึงพยายามส่งคืน a booleanfrom updateItemAttributesByJuId?
  2. จะแก้ไขได้อย่างไร?

คำตอบ:


199

ตามhttps://groups.google.com/forum/?fromgroups#!topic/mockito/9WUvkhZUy90คุณควรเปลี่ยนข้อความ

when(bar.getFoo()).thenReturn(fooBar)

ถึง

doReturn(fooBar).when(bar).getFoo()

3
นี่คือเคล็ดลับที่ดี ผมยังมีปัญหานี้เมื่อการทดสอบบางฤดูใบไม้ผลิ@Repositoryวิธี DAO กับ@Aspect ถ้าฉันทำwhen(someDao.someMethod()).thenReturn(List<xxx>)ฉันได้รับข้อยกเว้น WrongTypeOfReturnValue นี้ ผ่านการดีบักฉันเห็นได้ว่าsomeMethodวิธีนี้ถูกเรียกใช้จริงในข้อความข้างต้นและเรียกใช้คำแนะนำรอบ ๆ และส่งคืนnullแต่ Mockito คาดหวังว่าจะมีList<xxx>ไฟล์.
LeOn - Han Li

ทำงานให้ฉัน Obrigado!
นักเป่าแซ็กโซโฟน

คำตอบที่ยอดเยี่ยม มันบันทึกวันของฉัน
user3198259

ทำงานให้ฉันด้วย! ขอบคุณ! แม้ว่าฉันจะไม่เข้าใจคำอธิบายทั้งหมดในลิงก์ที่ให้มา
georgeliatsos

40

อีกสาเหตุหนึ่งสำหรับข้อความแสดงข้อผิดพลาดที่คล้ายกันคือพยายามล้อเลียนfinalวิธีการ เราไม่ควรพยายามล้อเลียนวิธีการขั้นสุดท้าย (ดูวิธีการล้อเลียนขั้นสุดท้าย )

ฉันยังพบข้อผิดพลาดในการทดสอบแบบมัลติเธรด ตอบโดย gna ทำงานในกรณีนั้น


20

ปัญหาที่สนใจมาก ในกรณีของฉันปัญหานี้เกิดขึ้นเมื่อฉันพยายามดีบักการทดสอบในบรรทัดที่คล้ายกันนี้:

Boolean fooBar;
when(bar.getFoo()).thenReturn(fooBar);

หมายเหตุสำคัญคือการทดสอบทำงานอย่างถูกต้องโดยไม่ต้องแก้ไขจุดบกพร่อง

แต่อย่างใดเมื่อฉันแทนที่โค้ดด้านบนด้วยข้อมูลโค้ดด้านล่างฉันก็สามารถดีบักบรรทัดปัญหาได้โดยไม่มีปัญหา

doReturn(fooBar).when(bar).getFoo();

ขอบคุณดูเหมือนว่าจะมีปัญหาเดียวกันกับคลาสข้อมูล Kotlin เป็นฟิลด์และโซลูชันของคุณก็แก้ไขได้!
Mohsen Mirhoseini

6

สำหรับฉันนี่หมายความว่าฉันกำลังเรียกใช้สิ่งนี้:

a = Mockito.mock(SomeClass.class);
b = new RealClass();
when(b.method1(a)).thenReturn(c); 
// within this method1, it calls param1.method2() -- note, b is not a spy or mock

สิ่งที่เกิดขึ้นคือม็อกโตะตรวจพบว่าa.method2()ถูกเรียกและบอกฉันว่าฉันไม่สามารถกลับcมาได้a.method2()ซึ่งผิด

แก้ไข: ใช้doReturn(c).when(b).method1(a)ไวยากรณ์สไตล์ (แทนwhen(b.method1(a)).thenReturn(c);) ซึ่งจะช่วยให้คุณค้นพบจุดบกพร่องที่ซ่อนอยู่ได้อย่างรัดกุมและรวดเร็วยิ่งขึ้น

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


1
ฉันก็ผิดพลาดเหมือนกัน ฉันล้อเลียนวิธีที่ใช้ใน method1 ดำเนินการและได้รับข้อยกเว้นนี้ ได้รับการแก้ไขเมื่อฉันลบรหัสนั้น
Praveen.883

5

ฉันเพิ่งมีปัญหานี้ ปัญหาคือวิธีที่ฉันพยายามล้อเลียนไม่มีตัวแก้ไขการเข้าถึง การเพิ่มสาธารณะช่วยแก้ปัญหาได้


5

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

MyClass cls = new MyClass();
MyClass cls2 = Mockito.mock(Myclass.class);
when(foo.bar(cls)).thenReturn(); // cls is not actually a mock
when(foo.baz(cls2)).thenReturn();

ฉันแก้ไขโดยเปลี่ยน cls ให้เป็นแบบจำลองเช่นกัน


4

ในกรณีของฉันปัญหาเกิดจากการพยายามล้อเลียนวิธีการแบบคงที่และลืมเรียกmockStaticเข้าชั้นเรียน ฉันลืมรวมชั้นเรียนไว้ในไฟล์@PrepareForTest()


2

หากคุณกำลังใช้คำอธิบายประกอบคุณอาจต้องใช้ @Mock แทน @InjectMocks เนื่องจาก @InjectMocks ทำงานเป็น @Spy และ @Mock ร่วมกัน และ @Spy ติดตามวิธีการดำเนินการล่าสุดและคุณอาจรู้สึกว่ามีการส่งคืน / ซับข้อมูลที่ไม่ถูกต้อง


2
" @InjectMocksทำงานเป็น @Spyและ@Mockร่วมกัน" <- ดูเหมือนจะผิดสำหรับฉัน คุณได้ยินสิ่งนี้มาจากไหน?
Etienne Miret

2

ในกรณีของฉันฉันใช้ทั้งสอง@RunWith(MockitoJUnitRunner.class)และMockitoAnnotations.initMocks(this). เมื่อฉันลบMockitoAnnotations.initMocks(this)มันทำงานได้อย่างถูกต้อง


1

ข้อผิดพลาด:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue:
ไม่สามารถส่งคืนสตริงตามขนาด ()
size () ควรส่งคืน int
***
หากคุณไม่แน่ใจว่าเหตุใดคุณจึงได้รับข้อผิดพลาดข้างต้นอ่าน
เนื่องจากลักษณะของไวยากรณ์ข้างต้นปัญหาอาจเกิดขึ้นเนื่องจาก:
1. ข้อยกเว้นนี้อาจเกิดขึ้นใน
การทดสอบแบบมัลติเธรดที่เขียนผิด
โปรดดูคำถามที่พบบ่อยของ Mockito เกี่ยวกับข้อ จำกัด ของการทดสอบพร้อมกัน
2. สายลับถูกขีดฆ่าโดยใช้ไวยากรณ์ when (spy.foo ()) แล้ว () มันปลอดภัยกว่าที่จะ ดักฟัง
สายลับ -
- ด้วยวิธีตระกูล doReturn | Throw () เพิ่มเติมใน javadocs สำหรับ
Mockito.spy () วิธีการ

รหัสจริง:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Object.class, ByteString.class})

@Mock
private ByteString mockByteString;

String testData = “dsfgdshf”;
PowerMockito.when(mockByteString.toStringUtf8()).thenReturn(testData); 
// throws above given exception

แนวทางแก้ไขปัญหานี้:

ครั้งแรกลบคำอธิบายประกอบ“ @Mock”

private ByteString mockByteString;

เพิ่มครั้งที่ 2 PowerMockito.mock

mockByteString = PowerMockito.mock(ByteString.class);

1

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

ฉันมั่นใจว่าฉันใช้org.mockito:mockito-inlineเพื่อหลีกเลี่ยงปัญหาเกี่ยวกับคลาสสุดท้าย (กล่าวถึงโดย Arvidaa) แต่ปัญหายังคงอยู่ สิ่งที่แก้ไขได้สำหรับฉันคือการฆ่ากระบวนการและรีสตาร์ท Android สตูดิโอ การดำเนินการนี้ยุติการทดสอบการแช่แข็งของฉันและการทดสอบต่อไปนี้ผ่านไปโดยไม่มีปัญหา



1

ฉันได้รับปัญหานี้WrongTypeOfReturnValueเนื่องจากฉันล้อเลียนวิธีที่ส่งคืนjava.util.Optional;a com.google.common.base.Optional;เนื่องจากฟอร์แมตเตอร์ของฉันเพิ่มการนำเข้าที่ขาดหายไปโดยอัตโนมัติ

Mockito แค่บอกฉันว่า "method something () should return optional" ...


1

ในกรณีของถั่วที่ได้รับการเริ่มต้นใช้@Autowiredคำอธิบายประกอบแทน@MockBean

ดังนั้นด้วยวิธีนี้การล้อเลียน DAO และบริการจึงทำให้เกิดข้อยกเว้นดังกล่าว


1
ใช่ในกรณีของฉันการทดสอบบริการแอปพลิเคชัน Spring-Boot ควรใช้ MockBean เมื่อล้อเลียน Bean ขอบคุณ!
Isaac Philip

1

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

นี่ไม่ใช่การทดสอบข้อเขียนโดยใช้ Mockito อย่างถูกต้อง ไม่ควรเข้าถึง Mocks จากหลายเธรด

วิธีแก้ปัญหาคือการทำ mocks ในท้องถิ่นสำหรับการทดสอบแต่ละครั้ง


1

TL; DRหากข้อโต้แย้งบางอย่างในการทดสอบของคุณnullให้แน่ใจว่าจะเยาะเย้ยโทรพารามิเตอร์ที่มีแทนisNull()anyXXX()


ฉันได้รับข้อผิดพลาดนี้เมื่ออัปเกรดจาก Spring boot 1.5.x เป็น 2.1.x Spring boot มาพร้อมกับ Mockito ของตัวเองซึ่งตอนนี้อัพเกรดเป็น 2.x ด้วย (ดูเช่นDependencies of Spring boot 2.1.2 )

Mockito มีการเปลี่ยนแปลงพฤติกรรมสำหรับanyXXX()วิธีการที่XXXเป็นString, Longฯลฯ นี่คือ Javadoc ของanyLong():

ตั้งแต่ Mockito 2.1.0 เพียง แต่ช่วยให้มูลค่าLongจึง nullไม่ได้อีกต่อไปค่าที่ถูกต้องในฐานะที่เป็นห่อดั้งเดิมเป็น nullable, API ที่แนะนำให้ตรงกับ เสื้อคลุมจะเป็นnull #isNull()เรารู้สึกว่าการเปลี่ยนแปลงนี้จะทำให้การทดสอบเทียมปลอดภัยยิ่งขึ้นเมื่อเทียบกับ Mockito 1.x.

ฉันขอแนะนำให้คุณแก้ไขข้อบกพร่องจนถึงจุดที่การเยาะเย้ยของคุณกำลังจะถูกเรียกและตรวจสอบว่ามีอาร์กิวเมนต์อย่างน้อยหนึ่งข้อnullหรือไม่ ในกรณีที่ทำให้แน่ใจว่าคุณเตรียมความพร้อมของคุณด้วยการเยาะเย้ยแทนเช่นisNull()anyLong()

ดังนั้นสิ่งนี้:

when(MockedClass.method(anyString());

กลายเป็น:

when(MockedClass.method(isNull());

-1

นี่คือกรณีของฉัน:

//given
ObjectA a = new ObjectA();
ObjectB b = mock(ObjectB.class);
when(b.call()).thenReturn(a);

Target target = spy(new Target());
doReturn(b).when(target).method1();

//when
String result = target.method2();

จากนั้นฉันได้รับข้อผิดพลาดนี้:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
ObjectB$$EnhancerByMockitoWithCGLIB$$2eaf7d1d cannot be returned by method2()
method2() should return String

คุณสามารถเดา?

ปัญหาคือ Target.method1 () เป็นวิธีการคงที่ Mockito เตือนฉันถึงอีกสิ่งหนึ่งอย่างสมบูรณ์

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