สแควร์ติดตั้งเซิร์ฟเวอร์จำลองสำหรับการทดสอบ


98

วิธีใดเป็นวิธีที่ดีที่สุดในการจำลองเซิร์ฟเวอร์เพื่อทดสอบเมื่อใช้ไฟล์ กรอบ retrofit ตาราง

วิธีที่เป็นไปได้:

  1. สร้างไคลเอนต์ติดตั้งใหม่และตั้งค่าใน RestAdapter.Builder (). setClient () สิ่งนี้เกี่ยวข้องกับการแยกวิเคราะห์อ็อบเจ็กต์ Request และส่งคืน json เป็นอ็อบเจ็กต์การตอบสนอง

  2. ใช้อินเทอร์เฟซที่มีคำอธิบายประกอบนี้เป็นคลาสจำลองและใช้แทนเวอร์ชันที่ RestAdapter.create () (จะไม่ทดสอบการทำให้เป็นอนุกรม gson)

  3. เหรอ?

ตามหลักการแล้วฉันต้องการให้เซิร์ฟเวอร์จำลองให้การตอบสนอง json ดังนั้นฉันจึงสามารถทดสอบการทำให้เป็นอนุกรม gson ได้ในเวลาเดียวกัน

ตัวอย่างใด ๆ จะได้รับการชื่นชมอย่างมาก


@JakeWharton มีจุดประสงค์เพื่อsquare-ossอะไร? retrofitดูเหมือนว่าที่กำหนดซ้ำซ้อน
Charles

@ อเล็กซ์โฮล์มส์: คุณแก้ปัญหาของคุณหรือยัง?
AndiGeeky

คำตอบ:


107

Mock Retrofit 2.0 คำขอสำหรับการทดสอบ

เนื่องจากกลไกเก่า ๆ เช่นการสร้างMockClientคลาสและการนำไปใช้งานClientไม่ทำงานอีกต่อไปกับ Retrofit 2.0 ฉันจึงอธิบายวิธีใหม่ในการทำเช่นนั้น ทุกสิ่งที่คุณต้องทำตอนนี้คือการเพิ่ม interceptors กำหนดเองของคุณสำหรับ OkHttpClient เหมือนว่ามันจะแสดงอยู่ด้านล่าง FakeInterceptorคลาสจะแทนที่interceptเมธอดและในกรณีที่แอปพลิเคชันอยู่ในDEBUGโหมดส่งคืนที่กำหนด JSON

RestClient.java

public final class RestClient {

    private static IRestService mRestService = null;

    public static IRestService getClient() {
        if(mRestService == null) {
            final OkHttpClient client = new OkHttpClient();
            // ***YOUR CUSTOM INTERCEPTOR GOES HERE***
            client.interceptors().add(new FakeInterceptor());

            final Retrofit retrofit = new Retrofit.Builder()
                            // Using custom Jackson Converter to parse JSON
                            // Add dependencies:
                            // com.squareup.retrofit:converter-jackson:2.0.0-beta2
                    .addConverterFactory(JacksonConverterFactory.create())
                            // Endpoint
                    .baseUrl(IRestService.ENDPOINT)
                    .client(client)
                    .build();

            mRestService = retrofit.create(IRestService.class);
        }
        return mRestService;
    }
}

IRestService.java

public interface IRestService {

    String ENDPOINT = "http://www.vavian.com/";

    @GET("/")
    Call<Teacher> getTeacherById(@Query("id") final String id);
}

FakeInterceptor.java

public class FakeInterceptor implements Interceptor { 
    // FAKE RESPONSES.
    private final static String TEACHER_ID_1 = "{\"id\":1,\"age\":28,\"name\":\"Victor Apoyan\"}";
    private final static String TEACHER_ID_2 = "{\"id\":1,\"age\":16,\"name\":\"Tovmas Apoyan\"}";

    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = null;
        if(BuildConfig.DEBUG) {
            String responseString;
            // Get Request URI.
            final URI uri = chain.request().url().uri();
            // Get Query String.
            final String query = uri.getQuery();
            // Parse the Query String.
            final String[] parsedQuery = query.split("=");
            if(parsedQuery[0].equalsIgnoreCase("id") && parsedQuery[1].equalsIgnoreCase("1")) {
                responseString = TEACHER_ID_1;
            }
            else if(parsedQuery[0].equalsIgnoreCase("id") && parsedQuery[1].equalsIgnoreCase("2")){
                responseString = TEACHER_ID_2;
            }
            else {
                responseString = "";
            }

            response = new Response.Builder()
                    .code(200)
                    .message(responseString)
                    .request(chain.request())
                    .protocol(Protocol.HTTP_1_0)
                    .body(ResponseBody.create(MediaType.parse("application/json"), responseString.getBytes()))
                    .addHeader("content-type", "application/json")
                    .build();
        }
        else {
            response = chain.proceed(chain.request());
        }

        return response;
    }
}

ซอร์สโค้ดของโครงการบนGitHub


10
เพื่อหลีกเลี่ยง UnsupportedOperationException ให้ใช้ OkHttpClient.Builder OkHttpClient สุดท้าย okHttpClient = ใหม่ OkHttpClient.Builder () .addInterceptor (FakeInterceptor ใหม่ ()) .build ();
จอห์น

4
สองปัญหาที่ฉันมี: 1- ไม่มีuri()ภายใต้chain.request().uri()(ฉันแก้ไขปัญหานี้โดยString url = chain.request().url().toString();ในกรณีของฉันแตกต่างกัน) 2- java.lang.IllegalStateException: network interceptor my.package.name.FakeInterceptor must call proceed() exactly onceฉันได้รับ ฉันได้เพิ่มรายการนี้ลงมากกว่าaddNetworkInterceptor() addInterceptor()
Hesam

2
ใช้ chain.request (). url (). uri ();
Amol Gupta

ฉันจะจำลองข้อผิดพลาด 401 เพื่อทดสอบเมธอด httpClient.authenticator ได้อย่างไร เพียงแค่ใส่รหัส "401" วิธีการตรวจสอบจะไม่เรียก ฉันจะจัดการเรื่องนี้ได้อย่างไร
Mahdi

ฉันได้ใช้วิธีการดักฟังปลอมเพื่อจำลองเว็บ apis ไปอีกระดับและเผยแพร่ห้องสมุดเล็ก ๆ เพื่อให้ง่ายและสะดวกยิ่งขึ้น ดู github.com/donfuxx/Mockinizer
donfuxx

85

ฉันตัดสินใจลองวิธีที่ 1 ดังต่อไปนี้

public class MockClient implements Client {

    @Override
    public Response execute(Request request) throws IOException {
        Uri uri = Uri.parse(request.getUrl());

        Log.d("MOCK SERVER", "fetching uri: " + uri.toString());

        String responseString = "";

        if(uri.getPath().equals("/path/of/interest")) {
            responseString = "JSON STRING HERE";
        } else {
            responseString = "OTHER JSON RESPONSE STRING";
        }

        return new Response(request.getUrl(), 200, "nothing", Collections.EMPTY_LIST, new TypedByteArray("application/json", responseString.getBytes()));
    }
}

และใช้โดย:

RestAdapter.Builder builder = new RestAdapter.Builder();
builder.setClient(new MockClient());

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


ฉันได้อัปเดตตัวสร้างการตอบกลับที่ใช้เนื่องจากตัวสร้างการตอบสนองเก่าเลิกใช้งานแล้วซึ่งกำลังขว้างIllegalArgumentException url == nullด้วยชุดติดตั้งเพิ่ม 1.4.1
แดน J

1
จำเป็นต้องเพิ่มจุดสิ้นสุดให้กับตัวสร้างด้วย:builder.setEndpoint("http://mockserver.com").setClient(new MockClient());
codeprogression

ฉันได้ขยายไคลเอนต์จำลองด้านบนเพื่อดึงการตอบสนองจากไฟล์ในโฟลเดอร์สินทรัพย์ขึ้นอยู่กับคำขอ URL
praveena_kd

21
ตอนนี้ชุดติดตั้งเพิ่ม 2 ใช้ OkHttpClient สำหรับเลเยอร์ไคลเอ็นต์และรหัสนี้ใช้ไม่ได้ ¿มีความคิดอย่างไรในการสร้าง OkHttpClient? อาจเป็นเรื่องเกี่ยวกับการขยายและการลบล้าง แต่ฉันไม่แน่ใจว่าจะทำอย่างไร
GuillermoMP

1
คุณสามารถอัปเดตคำตอบของคุณตาม Retrofit2 ได้หรือไม่? ขอบคุณ
Hesam

20

การทดสอบ JSON deserialization กับอ็อบเจ็กต์ของคุณ (น่าจะมีTypeAdapters?) ดูเหมือนจะเป็นปัญหาแยกต่างหากที่ต้องมีการทดสอบหน่วยแยกต่างหาก

ฉันใช้รุ่น 2 เป็นการส่วนตัว มีรหัสที่ปลอดภัยและเป็นมิตรต่อตัวรีแอคเตอร์ซึ่งสามารถแก้ไขและแก้ไขได้ง่าย ท้ายที่สุดแล้วสิ่งที่ดีคือการประกาศ API ของคุณเป็นอินเทอร์เฟซหากคุณไม่ได้สร้างเวอร์ชันอื่นสำหรับการทดสอบ! ความแตกต่างสำหรับการชนะ

อีกตัวเลือกหนึ่งคือการใช้ ProxyJava นี่เป็นวิธีที่ Retrofit (ปัจจุบัน) ใช้การโต้ตอบ HTTP ที่อยู่เบื้องหลัง สิ่งนี้จะต้องใช้งานมากขึ้น แต่จะช่วยให้มีการล้อเลียนแบบไดนามิกมากขึ้น


นี่ก็เป็นวิธีที่ฉันชอบเช่นกัน มันง่ายกว่ามากในการดีบักตามที่ระบุไว้ข้างต้นจากนั้นต้องจัดการโดยตรงกับเนื้อหาตอบสนอง @alec หากคุณต้องการทดสอบการทำให้อนุกรม GSON สร้าง / อ่านในสตริง json และใช้วัตถุ gson เพื่อแยกส่วน ภายใต้ศีรษะฉันเชื่อว่านั่นคือสิ่งที่ Retrofit ทำอยู่แล้ว
loeschg

@JakeWharton คุณช่วยให้ตัวอย่างสั้น ๆ เกี่ยวกับสิ่งที่ต้องการได้หรือไม่? ฉันมีปัญหาในการแสดงภาพนี้ ... ขอบคุณ!
uncle_tex



8

ฉันเป็นแฟนตัวยงของApiary.ioสำหรับการล้อเลียน API ก่อนที่จะย้ายไปยังเซิร์ฟเวอร์จริง

คุณยังสามารถใช้ไฟล์แบน. json และอ่านจากระบบไฟล์

คุณยังสามารถใช้ API ที่เข้าถึงได้แบบสาธารณะเช่น Twitter, Flickr เป็นต้น

นี่คือแหล่งข้อมูลที่ยอดเยี่ยมอื่น ๆ เกี่ยวกับชุดติดตั้งเพิ่มเติม

สไลด์: https://docs.google.com/presentation/d/12Eb8OPI0PDisCjWne9-0qlXvp_-R4HmqVCjigOIgwfY/edit#slide=id.p

วิดีโอ: http://www.youtube.com/watch?v=UtM06W51pPw&feature=g-user-u

ตัวอย่างโครงการ: https://github.com/dustin-graham/ucad_twitter_retrofit_sample


7

การเยาะเย้ย (ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียน) ได้รับการออกแบบมาเพื่องานนี้เท่านั้น

Mockery เป็นไลบรารีจำลอง / การทดสอบที่เน้นการตรวจสอบความถูกต้องของเลเยอร์เครือข่ายพร้อมการสนับสนุนในตัวสำหรับชุดติดตั้งเพิ่มเติม จะสร้างการทดสอบ JUnit โดยอัตโนมัติตามข้อกำหนดของ Api ที่กำหนด แนวคิดคือไม่จำเป็นต้องเขียนแบบทดสอบด้วยตนเอง ไม่ใช้อินเทอร์เฟซสำหรับจำลองการตอบสนองของเซิร์ฟเวอร์


7
  1. ขั้นแรกสร้างอินเทอร์เฟซ Retrofit ของคุณ

    public interface LifeKitServerService {
        /**
         * query event list from server,convert Retrofit's Call to RxJava's Observerable
         *
         * @return Observable<HttpResult<List<Event>>> event list from server,and it has been convert to Obseverable
         */
        @GET("api/event")
        Observable<HttpResult<List<Event>>> getEventList();
    }
    
  2. ผู้ร้องขอของคุณมีดังต่อไปนี้:

    public final class HomeDataRequester {
        public static final String TAG = HomeDataRequester.class.getSimpleName();
        public static final String SERVER_ADDRESS = BuildConfig.DATA_SERVER_ADDR + "/";
        private LifeKitServerService mServerService;
    
        private HomeDataRequester() {
            OkHttpClient okHttpClient = new OkHttpClient.Builder()
                    //using okhttp3 interceptor fake response.
                    .addInterceptor(new MockHomeDataInterceptor())
                    .build();
    
            Retrofit retrofit = new Retrofit.Builder()
                    .client(okHttpClient)
                    .baseUrl(SERVER_ADDRESS)
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .addConverterFactory(GsonConverterFactory.create(new Gson()))
                    .build();
    
            //using okhttp3 inteception to fake response.
            mServerService = retrofit.create(LifeKitServerService.class);
    
            //Second choice,use MockRetrofit to fake data.
            //NetworkBehavior behavior = NetworkBehavior.create();
            //MockRetrofit mockRetrofit = new MockRetrofit.Builder(retrofit)
            //        .networkBehavior(behavior)
            //        .build();
            //mServerService = new MockLifeKitServerService(
            //                    mockRetrofit.create(LifeKitServerService.class));
        }
    
        public static HomeDataRequester getInstance() {
            return InstanceHolder.sInstance;
        }
    
        public void getEventList(Subscriber<HttpResult<List<Event>>> subscriber) {
            mServerService.getEventList()
                    .subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(subscriber);
        }
    }
    
  3. หากคุณใช้ตัวเลือกที่สอง (ใช้อินเทอร์เฟซการติดตั้งเพิ่มเพื่อจำลองข้อมูลเซิร์ฟเวอร์) คุณต้อง MockRetrofit ใช้รหัสตาม:

    public final class MockLifeKitServerService implements LifeKitServerService {
    public static final String TAG = MockLifeKitServerService.class.getSimpleName();
    private BehaviorDelegate<LifeKitServerService> mDelegate;
    private Gson mGson = new Gson();
    
    public MockLifeKitServerService(BehaviorDelegate<LifeKitServerService> delegate) {
        mDelegate = delegate;
    }
    
    @Override
    public Observable<HttpResult<List<Event>>> getEventList() {
        List<Event> eventList = MockDataGenerator.generateEventList();
        HttpResult<List<Event>> httpResult = new HttpResult<>();
        httpResult.setCode(200);
        httpResult.setData(eventList);
    
        LogUtil.json(TAG, mGson.toJson(httpResult));
    
        String text = MockDataGenerator.getMockDataFromJsonFile("server/EventList.json");
        if (TextUtils.isEmpty(text)) {
            text = mGson.toJson(httpResult);
        }
        LogUtil.d(TAG, "Text:\n" + text);
    
        text = mGson.toJson(httpResult);
    
        return mDelegate.returningResponse(text).getEventList();
    }
    

4. ข้อมูลของฉันมาจากไฟล์สินทรัพย์ (สินทรัพย์ / เซิร์ฟเวอร์ / EventList.json) เนื้อหาไฟล์นี้คือ:

    {
      "code": 200,
      "data": [
        {
          "uuid": "e4beb3c8-3468-11e6-a07d-005056a05722",
          "title": "title",
          "image": "http://image.jpg",
          "goal": 1500000,
          "current": 51233,
          "hot": true,
          "completed": false,
          "createdAt": "2016-06-15T04:00:00.000Z"
        }
      ]
    }

5. หากคุณใช้ okhttp3 interceptor คุณต้องกำหนดตัวดักจับด้วยตนเองดังนี้:

public final class MockHomeDataInterceptor implements Interceptor {
    public static final String TAG = MockHomeDataInterceptor.class.getSimpleName();

    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = null;

        String path = chain.request().url().uri().getPath();
        LogUtil.d(TAG, "intercept: path=" + path);

        response = interceptRequestWhenDebug(chain, path);
        if (null == response) {
            LogUtil.i(TAG, "intercept: null == response");
            response = chain.proceed(chain.request());
        }
        return response;
    }

    private Response interceptRequestWhenDebug(Chain chain, String path) {
        Response response = null;
        if (BuildConfig.DEBUG) {
            Request request = chain.request();
            if (path.equalsIgnoreCase("/api/event")) {
                //get event list
                response = getMockEventListResponse(request);
            }
    }

    private Response getMockEventListResponse(Request request) {
        Response response;

        String data = MockDataGenerator.getMockDataFromJsonFile("server/EventList.json");
        response = getHttpSuccessResponse(request, data);
        return response;
    }

    private Response getHttpSuccessResponse(Request request, String dataJson) {
        Response response;
        if (TextUtils.isEmpty(dataJson)) {
            LogUtil.w(TAG, "getHttpSuccessResponse: dataJson is empty!");
            response = new Response.Builder()
                    .code(500)
                    .protocol(Protocol.HTTP_1_0)
                    .request(request)
                    //protocol&request be set,otherwise will be exception.
                    .build();
        } else {
            response = new Response.Builder()
                    .code(200)
                    .message(dataJson)
                    .request(request)
                    .protocol(Protocol.HTTP_1_0)
                    .addHeader("Content-Type", "application/json")
                    .body(ResponseBody.create(MediaType.parse("application/json"), dataJson))
                    .build();
        }
        return response;
    }
}

6. สุดท้ายคุณสามารถขอเซิร์ฟเวอร์ของคุณด้วยรหัส:

mHomeDataRequester.getEventList(new Subscriber<HttpResult<List<Event>>>() {
    @Override
    public void onCompleted() {

    }

    @Override
    public void onError(Throwable e) {
        LogUtil.e(TAG, "onError: ", e);
        if (mView != null) {
            mView.onEventListLoadFailed();
        }
    }

    @Override
    public void onNext(HttpResult<List<Event>> httpResult) {
        //Your json result will be convert by Gson and return in here!!!
    });
}

ขอบคุณที่อ่าน.


5

เพิ่มคำตอบโดย @Alec ฉันได้ขยายไคลเอนต์จำลองเพื่อรับการตอบกลับโดยตรงจากไฟล์ข้อความในโฟลเดอร์เนื้อหาโดยขึ้นอยู่กับ URL คำขอ

เช่น

@POST("/activate")
public void activate(@Body Request reqdata, Callback callback);

ที่นี่ไคลเอนต์จำลองเข้าใจว่า URL ที่ถูกยิงถูกเปิดใช้งานและค้นหาไฟล์ชื่อ enable.txt ในโฟลเดอร์ assets มันอ่านเนื้อหาจากไฟล์ assets / enable.txt และส่งเป็นคำตอบสำหรับ API

นี่คือส่วนขยาย MockClient

public class MockClient implements Client {
    Context context;

    MockClient(Context context) {
        this.context = context;
    }

    @Override
    public Response execute(Request request) throws IOException {
        Uri uri = Uri.parse(request.getUrl());

        Log.d("MOCK SERVER", "fetching uri: " + uri.toString());

        String filename = uri.getPath();
        filename = filename.substring(filename.lastIndexOf('/') + 1).split("?")[0];

        try {
            Thread.sleep(2500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        InputStream is = context.getAssets().open(filename.toLowerCase() + ".txt");
        int size = is.available();
        byte[] buffer = new byte[size];
        is.read(buffer);
        is.close();
        String responseString = new String(buffer);

        return new Response(request.getUrl(), 200, "nothing", Collections.EMPTY_LIST, new TypedByteArray("application/json", responseString.getBytes()));
    }
}

สำหรับคำอธิบายโดยละเอียดคุณสามารถชำระเงินในบล็อกของฉันได้ที่
http://www.cumulations.com/blogs/13/Mock-API-response-in-Retrofit-using-custom-clients


สวัสดีตอนที่ฉันกำลังเขียนคลาสทดสอบโดยใช้โรโบอิเล็กทริกและใช้ม็อคไคลเอนต์เพื่อเยาะเย้ย api การติดตั้งมันไม่ได้ให้คำตอบใด ๆ กับฉัน คุณช่วยแนะนำวิธีการทำสิ่งนี้ให้ฉันได้ไหม
Dory

สวัสดี @Dory ตรวจสอบให้แน่ใจว่าคุณมีส่วนลงท้าย URL และชื่อไฟล์ในโฟลเดอร์เนื้อหา ตัวอย่างเช่นสมมติว่า URL ของคุณมีดังต่อไปนี้ (ใช้ Reftrofit ที่นี่) @POST ("/ exchangeGyft") โมฆะสาธารณะ exchangeGyft (@Body MposRequest reqdata, Callback <RedeemGyftResponse> callback); แล้วชื่อไฟล์ในโฟลเดอร์ correspodning สินทรัพย์ redeemgyft.txt
praveena_kd

ฉันตั้งชื่อไฟล์แบบคงที่ในMockClientไฟล์ของฉันเขียนคลาสทดสอบโดยใช้โรโบอิเล็กทริก แต่ฉันไม่สามารถรับคำตอบใด ๆ จากไฟล์ json
Dory

หากคุณเก็บไฟล์ไว้ในโฟลเดอร์ assets ควรเลือกไฟล์นั้น
praveena_kd

1

JSONPlaceholder: Fake Online REST API สำหรับการทดสอบและการสร้างต้นแบบ

https://jsonplaceholder.typicode.com/

ReqresIn: Online REST API อื่น

https://reqres.in/

เซิร์ฟเวอร์จำลองบุรุษไปรษณีย์

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

ป้อนคำอธิบายภาพที่นี่ https://learning.getpostman.com/docs/postman/mock_servers/intro_to_mock_servers/ https://youtu.be/shYn3Ys3ygE


1

การจำลองการโทร api ด้วย Retrofit ทำได้ง่ายยิ่งขึ้นด้วยMockinizerซึ่งทำให้การทำงานกับ MockWebServer ตรงไปตรงมาอย่างแท้จริง:

import com.appham.mockinizer.RequestFilter
import okhttp3.mockwebserver.MockResponse

val mocks: Map<RequestFilter, MockResponse> = mapOf(

    RequestFilter("/mocked") to MockResponse().apply {
        setResponseCode(200)
        setBody("""{"title": "Banana Mock"}""")
    },

    RequestFilter("/mockedError") to MockResponse().apply {
        setResponseCode(400)
    }

)

เพียงสร้างแผนที่ของRequestFilter และ MockResponsesจากนั้นเสียบเข้ากับโซ่ตัวสร้าง OkHttpClient ของคุณ:

OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .mockinize(mocks) // <-- just plug in your custom mocks here
            .build()

คุณไม่ต้องกังวลกับการกำหนดค่า MockWebServer และอื่น ๆ เพียงแค่เพิ่ม mocks ของคุณส่วนที่เหลือทั้งหมดก็ทำได้โดย Mockinizer สำหรับคุณ

(คำเตือน: ฉันเป็นคนเขียน Mockinizer)


0

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

แก้ไข: ที่นี่คุณพบตัวอย่างการล้อเลียนการติดตั้งเพิ่มเติม https://github.com/pawelByszewski/retrofitmock

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