วิธีการเลียนแบบชั้นเรียนสุดท้ายด้วย mockito


218

ฉันมีชั้นเรียนสุดท้ายสิ่งนี้:

public final class RainOnTrees{

   public void startRain(){

        // some code here
   }
}

ฉันใช้คลาสนี้ในคลาสอื่นเช่นนี้:

public class Seasons{

   RainOnTrees rain = new RainOnTrees();

   public void findSeasonAndRain(){

        rain.startRain();

    }
}

และในชั้นทดสอบ JUnit ของฉันสำหรับSeasons.javaฉันต้องการเยาะเย้ยRainOnTreesชั้นเรียน ฉันจะทำสิ่งนี้กับ Mockito ได้อย่างไร


9
Mockito ไม่อนุญาต แต่ PowerMock ทำ
fge

1
ในฐานะของ Mockito 2.x ขณะนี้ Mockito สนับสนุนการเยาะเย้ยของคลาสและวิธีการขั้นสุดท้าย
Kent

คำตอบ:


155

การเยาะเย้ยชั้นเรียนสุดท้าย / คงที่ / วิธีการเป็นไปได้กับ Mockito v2 เท่านั้น

เพิ่มในไฟล์ gradle ของคุณ:

testImplementation 'org.mockito:mockito-inline:2.13.0'

สิ่งนี้ไม่สามารถทำได้กับ Mockito v1 จากคำถามที่พบบ่อยของ Mockito :

ข้อ จำกัด ของ Mockito คืออะไร

  • ต้องการ java 1.5+

  • ไม่สามารถเลียนแบบคลาสสุดท้าย

...


2
สิ่งนี้ไม่ได้ผลสำหรับฉันใน Scala (ด้วยการปรับเปลี่ยน sbt)
micseydel

2
แค่นี้ก็ไม่พอสำหรับฉัน ฉันยังต้องสร้าง src / test / resources / mockito-extensions / org.mockito.plugins.MockMaker ด้วย "mock-maker-inline" ในนั้นตามbaeldung.com/mockito-final
micseydel

204

Mockito 2 รองรับคลาสและวิธีการขั้นสุดท้ายแล้ว!

แต่ตอนนี้เป็นคุณลักษณะ "ฟักไข่" มันต้องมีขั้นตอนบางอย่างเพื่อเปิดใช้งานซึ่งอธิบายไว้ในมีอะไรใหม่ใน Mockito 2 :

การเยาะเย้ยของคลาสและวิธีการขั้นสุดท้ายคือการบ่มเพาะการเลือกเข้าร่วม มันใช้การรวมกันของเครื่องมือตัวแทนเอเจนต์ Java และ subclassing เพื่อเปิดใช้งานการเยาะเย้ยประเภทเหล่านี้ เนื่องจากสิ่งนี้ทำงานได้แตกต่างจากกลไกปัจจุบันของเราและสิ่งนี้มีข้อ จำกัด ที่แตกต่างกันและเมื่อเราต้องการรวบรวมประสบการณ์และความคิดเห็นจากผู้ใช้คุณลักษณะนี้จึงต้องเปิดใช้งานอย่างชัดเจนเพื่อให้พร้อมใช้งาน มันสามารถทำได้ผ่านกลไกการขยาย mockito โดยการสร้างไฟล์src/test/resources/mockito-extensions/org.mockito.plugins.MockMakerที่มีบรรทัดเดียว:

mock-maker-inline

หลังจากที่คุณสร้างไฟล์นี้ Mockito จะใช้เอ็นจิ้นใหม่นี้โดยอัตโนมัติและสามารถทำได้:

 final class FinalClass {
   final String finalMethod() { return "something"; }
 }

 FinalClass concrete = new FinalClass(); 

 FinalClass mock = mock(FinalClass.class);
 given(mock.finalMethod()).willReturn("not anymore");

 assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());

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


14
ฉันยังคงได้รับข้อผิดพลาด: ไม่สามารถจำลอง / สอดแนมคลาส android.content.ComponentName Mockito ไม่สามารถจำลอง / สอดแนมได้เนื่องจาก: - คลาสสุดท้าย
IgorGanapolsky

3
ตรวจสอบให้แน่ใจว่าคุณใส่org.mockito.plugins.MockMakerไฟล์ในโฟลเดอร์ที่ถูกต้อง
WindRider

7
ฉันยังได้รับข้อผิดพลาดแม้หลังจากทำตามที่กล่าวไว้ข้างต้น: Mockito ไม่สามารถเยาะเย้ย / สืบเนื่องจาก: - คลาสสุดท้าย
rcde0

8
@vCillusion คำตอบนี้ไม่เกี่ยวข้องกับ PowerMock แต่อย่างใด
สาย

6
ฉันทำตามคำแนะนำเหล่านี้ แต่ฉันก็ยังทำงานนี้ไม่ได้มีใครทำอะไรอย่างอื่นอีกหรือเปล่า?
Franco

43

คุณไม่สามารถล้อเลียนคลาสสุดท้ายกับ Mockito ได้เนื่องจากคุณไม่สามารถทำได้ด้วยตัวเอง

สิ่งที่ฉันทำคือการสร้างคลาสที่ไม่ใช่ครั้งสุดท้ายเพื่อห่อคลาสสุดท้ายและใช้เป็นตัวแทน ตัวอย่างของนี่คือTwitterFactoryคลาสและนี่คือคลาสที่เยาะเย้ยของฉัน:

public class TwitterFactory {

    private final twitter4j.TwitterFactory factory;

    public TwitterFactory() {
        factory = new twitter4j.TwitterFactory();
    }

    public Twitter getInstance(User user) {
        return factory.getInstance(accessToken(user));
    }

    private AccessToken accessToken(User user) {
        return new AccessToken(user.getAccessToken(), user.getAccessTokenSecret());
    }

    public Twitter getInstance() {
        return factory.getInstance();
    }
}

ข้อเสียคือมีรหัสสำเร็จรูปจำนวนมาก ข้อดีคือคุณสามารถเพิ่มวิธีการบางอย่างที่อาจเกี่ยวข้องกับธุรกิจแอปพลิเคชันของคุณ (เช่น getInstance ที่ใช้ผู้ใช้แทน accessToken ในกรณีข้างต้น)

ในกรณีของคุณฉันจะสร้างRainOnTreesชั้นเรียนที่ไม่ใช่ครั้งสุดท้ายที่มอบสิทธิ์ให้กับชั้นเรียนสุดท้าย หรือถ้าคุณทำให้มันไม่จบมันจะดีกว่า


6
+1 หากต้องการคุณสามารถใช้บางอย่างเช่นลอมบอก@Delegateเพื่อจัดการกับหม้อไอน้ำจำนวนมาก
ruakh

2
@luigi คุณสามารถเพิ่มข้อมูลโค้ดสำหรับ Junit เป็นตัวอย่างได้ ฉันพยายามสร้าง Wrapper สำหรับชั้นเรียนสุดท้ายของฉัน แต่ไม่สามารถหาวิธีทดสอบได้
เหลือเชื่อ

31

เพิ่มในไฟล์ gradle ของคุณ:

testImplementation 'org.mockito:mockito-inline:2.13.0'

นี่คือการกำหนดค่าเพื่อให้ mockito สามารถทำงานกับคลาสสุดท้ายได้


1
ควรใช้ "testImplementation" ตอนนี้แทนที่จะใช้ "testCompile" Gradle ไม่ชอบ "testCompile" อีกต่อไป
jwehrle

ความคิดเห็นที่ดีขอบคุณ! แก้ไขเพื่อทดสอบการใช้งาน ความคิดเห็นเดิม: testCompile 'org.mockito: mockito-inline: 2.13.0'
BennyP

2
ซึ่งส่งผลให้เกิดข้อผิดพลาดเมื่อทำงานบน Linux / OpenJDK 1.8:org.mockito.exceptions.base.MockitoInitializationException: Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)
naXa

ทำงานได้ดีเมื่อเปลี่ยนเป็น Oracle JDK 1.8
naXa

23

ใช้ Powermock ลิงก์นี้แสดงวิธีการ: https://github.com/jayway/powermock/wiki/MockFinal


30
ฉันคิดว่า PowerMock เป็นเหมือนหนึ่งในยาเหล่านั้นที่ควรออกไปที่ฐาน "ใบสั่งยา" เท่านั้น ในความรู้สึกของคนหนึ่งควรจะทำให้มันชัดเจนมากว่า PowerMock มีจำนวนมากของปัญหา และการใช้มันก็เหมือนเป็นทางเลือกสุดท้าย และควรหลีกเลี่ยงให้มากที่สุด
GhostCat

1
ทำไมคุณพูดแบบนั้น?
PragmaticProgrammer

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

16

เพียงเพื่อติดตาม โปรดเพิ่มบรรทัดนี้ในไฟล์ gradle ของคุณ:

testCompile group: 'org.mockito', name: 'mockito-inline', version: '2.8.9'

ฉันได้ลอง mockito-core และ mockito-all เวอร์ชันต่างๆแล้ว ไม่ทำงานเลย


1
เพื่อเพิ่มสิ่งนี้สิ่งหนึ่งที่ฉันสังเกตคือถ้าคุณใช้ Powermock พร้อมกับ mockito; จากนั้นเพิ่มไฟล์ปลั๊กอิน mockmaker ใน 'src / test / resources / mockito-extensions / org.mockito.plugins.MockMaker' จะไม่มีประโยชน์ในการเยาะเย้ยคลาสสุดท้าย การเพิ่มการพึ่งพาเช่น Michael_Zhang ที่กล่าวถึงข้างต้นจะช่วยแก้ปัญหาการเยาะเย้ยคลาสสุดท้าย นอกจากนี้ตรวจสอบให้แน่ใจว่าคุณใช้ Mockito 2 แทน Mockito1
dishooom

12

ผมคิดว่าคุณทำมันfinalเพราะคุณต้องการที่จะป้องกันไม่ให้ชั้นเรียนอื่น ๆ RainOnTreesจากการขยาย ตามที่มีผลบังคับใช้ Javaแนะนำ (ข้อ 15) มีวิธีอื่นในการปิดชั้นเรียนเพื่อการขยายโดยไม่ต้องทำfinal:

  1. ลบfinalคำหลัก;

  2. สร้างคอนสตรัprivateค ไม่มีคลาสใดที่สามารถขยายได้เนื่องจากจะไม่สามารถเรียกตัวsuperสร้างได้

  3. สร้างวิธีการผลิตจากโรงงานเพื่อสร้างคลาสของคุณ

    // No more final keyword here.
    public class RainOnTrees {
    
        public static RainOnTrees newInstance() {
            return new RainOnTrees();
        }
    
    
        private RainOnTrees() {
            // Private constructor.
        }
    
        public void startRain() {
    
            // some code here
        }
    }

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


1
วิธีนี้ใช้ไม่ได้กับวิธีการสุดท้ายซึ่งมี mockito 2 สามารถล้อเลียนได้
Łukasz Rzeszotarski

11

ผมมีปัญหาเหมือนกัน. ตั้งแต่ชั้นเรียนที่ฉันพยายามที่จะเยาะเย้ยเป็นชั้นเรียนที่เรียบง่ายฉันก็สร้างตัวอย่างของมันและกลับมาที่


2
แน่นอนทำไมเยาะเย้ยชั้นเรียนที่เรียบง่าย? การเยาะเย้ยเป็นการโต้ตอบ 'แพง': บริการอื่น ๆ เครื่องมือข้อมูลคลาสเป็นต้น
StripLight

3
หากคุณสร้างอินสแตนซ์ของสิ่งนั้นคุณจะไม่สามารถใช้วิธี Mockito.verify ได้ในภายหลัง การใช้งานหลักของ mocks คือการทดสอบวิธีการบางอย่าง
riroo

6

ลองดูสิ:

Mockito.mock(SomeMockableType.class,AdditionalAnswers.delegatesTo(someInstanceThatIsNotMockableOrSpyable));

มันใช้งานได้สำหรับฉัน "SomeMockableType.class" เป็นคลาสพาเรนต์ของสิ่งที่คุณต้องการจำลองหรือสอดแนมและ someInstanceThatIsNotMockableOrSpyable เป็นคลาสจริงที่คุณต้องการจำลองหรือสอดแนม

ดูรายละเอียดเพิ่มเติมได้ที่นี่


3
ควรสังเกตว่าผู้ได้รับมอบหมายแตกต่างจากการแอบดูสายลับดั้งเดิม ในสายลับ mockito ดั้งเดิม "นี่" ในอินสแตนซ์ที่อ้างอิงถึงสายลับตัวเอง (เพราะใช้คลาสย่อย) อย่างไรก็ตามในผู้แทน "นี่" จะเป็นวัตถุจริงบางอย่าง ไม่ใช่สายลับ ดังนั้นจึงไม่มีวิธีที่จะกลับมา / ตรวจสอบฟังก์ชั่นการโทรด้วยตนเอง
Dennis C

1
คุณยกตัวอย่างได้ไหม?
Vishwa Ratna

5

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


5

จริงๆแล้วมีวิธีหนึ่งที่ฉันใช้ในการสอดแนม มันจะทำงานสำหรับคุณเฉพาะในกรณีที่เงื่อนไขสองประการเป็นที่พอใจ:

  1. คุณใช้ DI บางชนิดในการฉีดอินสแตนซ์ของคลาสสุดท้าย
  2. ชั้นสุดท้ายใช้อินเทอร์เฟซ

โปรดจำรายการที่ 16 จากที่มีประสิทธิภาพ Java คุณสามารถสร้างเสื้อคลุม (ไม่ใช่ขั้นสุดท้าย) และโอนสายเรียกเข้าไปยังอินสแตนซ์ของคลาสสุดท้าย:

public final class RainOnTrees implement IRainOnTrees {
    @Override public void startRain() { // some code here }
}

public class RainOnTreesWrapper implement IRainOnTrees {
    private IRainOnTrees delegate;
    public RainOnTreesWrapper(IRainOnTrees delegate) {this.delegate = delegate;}
    @Override public void startRain() { delegate.startRain(); }
}

ตอนนี้ไม่เพียง แต่คุณสามารถเยาะเย้ยชั้นเรียนสุดท้ายของคุณ แต่ยังสอดแนมในชั้นเรียน:

public class Seasons{
    RainOnTrees rain;
    public Seasons(IRainOnTrees rain) { this.rain = rain; };
    public void findSeasonAndRain(){
        rain.startRain();
   }
}

IRainOnTrees rain = spy(new RainOnTreesWrapper(new RainOnTrees()) // or mock(IRainOnTrees.class)
doNothing().when(rain).startRain();
new Seasons(rain).findSeasonAndRain();

5

ใน Mockito 3 ขึ้นไปฉันมีปัญหาเดียวกันและแก้ไขได้จากลิงก์นี้

จำลองคลาสและวิธีการสุดท้ายด้วย Mockito ดังนี้

ก่อนที่จะสามารถใช้ Mockito สำหรับการจำลองชั้นเรียนและวิธีการขั้นสุดท้ายจำเป็นต้องมีการกำหนดค่า>

เราจำเป็นต้องเพิ่มไฟล์ข้อความในไดเร็กทอรี src / test / resources / mockito-extensions ชื่อ org.mockito.plugins.MockMaker และเพิ่มข้อความบรรทัดเดียว:

mock-maker-inline

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


4

ประหยัดเวลาสำหรับผู้ที่กำลังเผชิญปัญหาเดียวกัน (Mockito + ชั้นสุดท้าย) บน Android + Kotlin เช่นเดียวกับในคลาส Kotlin ถือเป็นที่สิ้นสุดโดยค่าเริ่มต้น ฉันพบวิธีแก้ไขในตัวอย่าง Google Android ที่มีองค์ประกอบสถาปัตยกรรม โซลูชันที่เลือกจากที่นี่: https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample

สร้างคำอธิบายประกอบต่อไปนี้:

/**
 * This annotation allows us to open some classes for mocking purposes while they are final in
 * release builds.
 */
@Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class OpenClass

/**
 * Annotate a class with [OpenForTesting] if you want it to be extendable in debug builds.
 */
@OpenClass
@Target(AnnotationTarget.CLASS)
annotation class OpenForTesting

แก้ไขไฟล์ gradle ของคุณ ใช้ตัวอย่างจากที่นี่: https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/build.gradle

apply plugin: 'kotlin-allopen'

allOpen {
    // allows mocking for classes w/o directly opening them for release builds
    annotation 'com.android.example.github.testing.OpenClass'
}

ตอนนี้คุณสามารถใส่คำอธิบายประกอบชั้นเรียนใด ๆ เพื่อให้เปิดสำหรับการทดสอบ:

@OpenForTesting
class RepoRepository 

สิ่งนี้ทำงานได้ดีในระดับแอป build.gradle แต่เราจะทำอย่างไรเพื่อให้ได้ระดับไลบรารี
Sumit T

คุณอธิบายรายละเอียดเล็กน้อยได้ไหม? โดยปกติใช้รูปแบบซุ้มเพื่อเชื่อมต่อกับ libs และจำลองคลาสซุ้มเหล่านี้เพื่อทดสอบแอป ด้วยวิธีนี้เราไม่จำเป็นต้องจำลองคลาส lib ใด ๆ
Ozeetee

3

สิ่งนี้สามารถทำได้หากคุณใช้ Mockito2 ด้วยคุณลักษณะการฟักตัวใหม่ที่รองรับการเยาะเย้ยของคลาสและวิธีการขั้นสุดท้าย

ประเด็นสำคัญที่ควรทราบ:
1. สร้างไฟล์อย่างง่ายด้วยชื่อ“ org.mockito.plugins.MockMaker” และวางไว้ในโฟลเดอร์ชื่อ“ mockito-extensions” โฟลเดอร์นี้ควรมีอยู่ใน classpath
2. เนื้อหาของไฟล์ที่สร้างขึ้นข้างต้นควรเป็นบรรทัดเดียวตามที่ระบุด้านล่าง:
mock-maker-inline

จำเป็นต้องใช้สองขั้นตอนข้างต้นเพื่อเปิดใช้งานกลไกการขยาย mockito และใช้คุณสมบัติการเลือกใช้นี้

ชั้นเรียนตัวอย่างมีดังนี้: -

FinalClass.java

public final class FinalClass {

public final String hello(){
    System.out.println("Final class says Hello!!!");
    return "0";
}

}

Foo.java

public class Foo {

public String executeFinal(FinalClass finalClass){
    return finalClass.hello();
}

}

FooTest.java

public class FooTest {

@Test
public void testFinalClass(){
    // Instantiate the class under test.
    Foo foo = new Foo();

    // Instantiate the external dependency
    FinalClass realFinalClass = new FinalClass();

    // Create mock object for the final class. 
    FinalClass mockedFinalClass = mock(FinalClass.class);

    // Provide stub for mocked object.
    when(mockedFinalClass.hello()).thenReturn("1");

    // assert
    assertEquals("0", foo.executeFinal(realFinalClass));
    assertEquals("1", foo.executeFinal(mockedFinalClass));

}

}

หวังว่ามันจะช่วย

ปัจจุบันบทความสมบูรณ์ที่นี่เยาะเย้ยที่ unmockable


คุณควรรวมคำตอบไว้ที่นี่และไม่เชื่อมโยงกับเว็บไซต์ภายนอก หากขั้นตอนนั้นยาวคุณสามารถรวมภาพรวมได้
rghome

โปรดตรวจสอบให้แน่ใจว่ามีการใช้คำอธิบายประกอบด้านล่างเมื่อเยาะเย้ย @RunWith (PowerMockRunner.class) @PrepareForTest ({AFinalClass.class})
vCillusion

1
@vCillusion - ตัวอย่างที่ฉันแสดงให้เห็นก็แค่ใช้ Mockito2 API โดยใช้คุณสมบัติการเลือกใช้ของ Mockito2 เราสามารถจำลองชั้นเรียนสุดท้ายได้โดยตรงโดยไม่ต้องใช้ Powermock
ksl

2

ใช่ปัญหาเดียวกันที่นี่เราไม่สามารถจำลองชั้นเรียนสุดท้ายด้วย Mockito เพื่อความถูกต้อง Mockito ไม่สามารถล้อเลียน / สอดแนมต่อไปนี้:

  • ชั้นเรียนสุดท้าย
  • คลาสที่ไม่ระบุชื่อ
  • ประเภทดั้งเดิม

แต่การใช้คลาส wrapper นั้นดูเหมือนว่าฉันจะต้องจ่ายเงินจำนวนมากดังนั้นรับ PowerMockito แทน


2

ฉันคิดว่าคุณต้องคิดในหลักการมากกว่านี้ แต่คุณในชั้นสุดท้ายใช้อินเตอร์เฟสและอินเตอร์เฟสจำลองแทน

สำหรับสิ่งนี้:

 public class RainOnTrees{

   fun startRain():Observable<Boolean>{

        // some code here
   }
}

เพิ่ม

interface iRainOnTrees{
  public void startRain():Observable<Boolean>
}

และจำลองส่วนต่อประสานกับคุณ:

 @Before
    fun setUp() {
        rainService= Mockito.mock(iRainOnTrees::class.java)

        `when`(rainService.startRain()).thenReturn(
            just(true).delay(3, TimeUnit.SECONDS)
        )

    }

1

กรุณาดูที่JMockit มันมีเอกสารมากมายพร้อมตัวอย่างมากมาย ที่นี่คุณมีตัวอย่างวิธีแก้ปัญหาของคุณ (เพื่อให้ง่ายขึ้นฉันได้เพิ่มตัวสร้างไปSeasonsยังRainOnTreesอินสแตนซ์ที่เยาะเย้ย):

package jmockitexample;

import mockit.Mocked;
import mockit.Verifications;
import mockit.integration.junit4.JMockit;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(JMockit.class)
public class SeasonsTest {

    @Test
    public void shouldStartRain(@Mocked final RainOnTrees rain) {
        Seasons seasons = new Seasons(rain);

        seasons.findSeasonAndRain();

        new Verifications() {{
            rain.startRain();
        }};
    }

    public final class RainOnTrees {
        public void startRain() {
            // some code here
        }

    }

    public class Seasons {

        private final RainOnTrees rain;

        public Seasons(RainOnTrees rain) {
            this.rain = rain;
        }

        public void findSeasonAndRain() {
            rain.startRain();
        }

    }
}

1

โซลูชันที่ RC และ Luigi R. Viggiano นำเสนอให้กันอาจเป็นแนวคิดที่ดีที่สุด

แม้ว่า Mockito ไม่สามารถโดยการออกแบบการเรียนสุดท้ายจำลองวิธีการที่คณะผู้แทนเป็นไปได้ นี่คือข้อดี:

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

ในกรณีทดสอบของคุณคุณตั้งใจส่งต่อสายไปยังระบบภายใต้การทดสอบ ดังนั้นด้วยการออกแบบการตกแต่งของคุณจึงไม่ทำอะไรเลย

ดังนั้นคุณทดสอบสามารถแสดงให้เห็นว่าผู้ใช้สามารถตกแต่ง API แทนการขยาย

ในบันทึกส่วนตัวเพิ่มเติม: ฉันชอบที่จะรักษากรอบให้น้อยที่สุดซึ่งเป็นเหตุผลที่ JUnit และ Mockito มักจะเพียงพอสำหรับฉัน อันที่จริงการ จำกัด วิธีนี้บางครั้งก็บังคับให้ฉันต้องปรับโครงสร้างให้ดีเช่นกัน


1

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

แต่ถ้าคุณต้องการเรียกใช้งานกับคลาสที่เกี่ยวข้องกับ Androidเช่นบริบทหรือกิจกรรมที่อยู่ภายใต้โฟลเดอร์androidtest คำตอบสำหรับคุณคือ


1

เพิ่มการขึ้นต่อกันเหล่านี้สำหรับการเรียกใช้ mockito สำเร็จ:

testImplementation 'org.mockito: mockito-core: 2.24.5'
testImplementation "org.mockito: mockito-inline: 2.24.5"


0

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

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


1
คลาส API สาธารณะควรเปิดเพื่อขยาย เห็นด้วยอย่างยิ่ง อย่างไรก็ตามในฐานรหัสส่วนตัวfinalควรเป็นค่าเริ่มต้น
ErikE

0

สำหรับเรามันเป็นเพราะเราไม่รวม mockito-inline จากการทดสอบ koin หนึ่งโมดูล gradle จำเป็นต้องใช้สิ่งนี้จริง ๆ และด้วยเหตุผลล้มเหลวในการสร้างรีลีสเท่านั้น (debug builds ใน IDE ทำงาน) :-P


0

สำหรับคลาสสุดท้ายเพิ่มด้านล่างเพื่อเยาะเย้ยและโทรคงที่หรือไม่คงที่

1- เพิ่มสิ่งนี้ในระดับชั้น @SuppressStatucInitializationFor (ค่า = {ชื่อคลาสพร้อมแพ็คเกจ})
2- PowerMockito.mockStatic (classname.class) จะเยาะเย้ยคลาส
3- จากนั้นใช้คำสั่งของคุณเพื่อส่งคืนวัตถุจำลองเมื่อเรียกเมธอดของคลาสนี้

สนุก


-5

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


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