国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

App開(kāi)發(fā):模擬服務(wù)器數(shù)據(jù)接口 - MockApi

2019-11-14 12:51:15
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友


為了方便app開(kāi)發(fā)過(guò)程中,不受服務(wù)器接口的限制,便于客戶端功能的快速測(cè)試,可以在客戶端實(shí)現(xiàn)一個(gè)模擬服務(wù)器數(shù)據(jù)接口的MockApi模塊。本篇文章就嘗試為使用gradle的android項(xiàng)目設(shè)計(jì)實(shí)現(xiàn)MockApi。

需求概述

在app開(kāi)發(fā)過(guò)程中,在和服務(wù)器人員協(xié)作時(shí),一般會(huì)第一時(shí)間確定數(shù)據(jù)接口的請(qǐng)求參數(shù)和返回?cái)?shù)據(jù)格式,然后服務(wù)器人員會(huì)盡快提供給客戶端可調(diào)試的假數(shù)據(jù)接口。不過(guò)有時(shí)候就算是假數(shù)據(jù)接口也來(lái)不及提供,或者是接口數(shù)據(jù)格式來(lái)回變動(dòng)——很可能是客戶端展示的原因,這個(gè)是產(chǎn)品設(shè)計(jì)決定的,總之帶來(lái)的問(wèn)題就算服務(wù)器端的開(kāi)發(fā)進(jìn)度會(huì)影響客戶端。

所以,如果可以在客戶端的正常項(xiàng)目代碼中,自然地(不影響最終apk)添加一種模擬服務(wù)器數(shù)據(jù)返回的功能,這樣就可以很方便的在不依賴服務(wù)器的情況下展開(kāi)客戶端的開(kāi)發(fā)。而且考慮一種情況,為了測(cè)試不同網(wǎng)絡(luò)速度,網(wǎng)絡(luò)異常以及服務(wù)器錯(cuò)誤等各種“可能的真實(shí)數(shù)據(jù)請(qǐng)求的場(chǎng)景”對(duì)客戶端UI交互的影響,我們往往需要做很多手動(dòng)測(cè)試——千篇一律!如果本地有一種控制這種服務(wù)器響應(yīng)行為的能力那真是太好了。

本文將介紹一種為客戶端項(xiàng)目增加模擬數(shù)據(jù)接口功能的方式,希望能減少一些開(kāi)發(fā)中的煩惱。

設(shè)計(jì)過(guò)程

下面從分層設(shè)計(jì)、可開(kāi)關(guān)模擬模塊、不同網(wǎng)絡(luò)請(qǐng)求結(jié)果的制造這幾個(gè)方面來(lái)闡述下模擬接口模塊的設(shè)計(jì)。為了表達(dá)方便,這里要實(shí)現(xiàn)的功能表示為“數(shù)據(jù)接口模擬模塊”,對(duì)應(yīng)英文為MockDataApi,或簡(jiǎn)寫(xiě)為MockApi,正常的數(shù)據(jù)接口模塊定義為DataApi。

分層思想

說(shuō)到分層設(shè)計(jì),MVC、MVP等模式一定程度上就起到了對(duì)代碼所屬功能的一個(gè)劃分。分層設(shè)計(jì)簡(jiǎn)單的目標(biāo)就是讓項(xiàng)目代碼更加清晰,各層相互獨(dú)立,好處不多說(shuō)。

移動(dòng)app的邏輯主要就是交互邏輯,然后需要和服務(wù)器溝通數(shù)據(jù)。所以最簡(jiǎn)單的情形下可以將一個(gè)功能(比如一個(gè)列表界面)的實(shí)現(xiàn)分UI層和數(shù)據(jù)訪問(wèn)層。

下面將數(shù)據(jù)訪問(wèn)層表述為DataApi模塊,DataApi層會(huì)定義一系列的接口來(lái)描述不同類別的數(shù)據(jù)訪問(wèn)請(qǐng)求。UI層使用這些接口來(lái)獲取數(shù)據(jù),而具體的數(shù)據(jù)訪問(wèn)實(shí)現(xiàn)類就可以在不修改UI層代碼的情況下進(jìn)行替換。

例如,有一個(gè)ITaskApi定義了方法List<Task> getTasks(),UI層一個(gè)界面展示任務(wù)列表,那么它使用ITaskApi來(lái)獲取數(shù)據(jù),而具體ITaskApi的實(shí)現(xiàn)類可以由DataApi層的一個(gè)工廠類DataApiManager來(lái)統(tǒng)一提供。

有了上面的分層設(shè)計(jì),就可以為UI層動(dòng)態(tài)提供真實(shí)數(shù)據(jù)接口或模擬數(shù)據(jù)接口。

模擬接口的開(kāi)關(guān)

可能大家都經(jīng)歷過(guò)在UI層代碼里臨時(shí)寫(xiě)一些假數(shù)據(jù)得情況。比如任務(wù)列表界面,開(kāi)發(fā)初,可以寫(xiě)一個(gè)mockTaskData()方法來(lái)返回一個(gè)List<Task>。但這種代碼只能是開(kāi)發(fā)階段有,最終apk不應(yīng)該存在。

不能讓“模擬數(shù)據(jù)”的代碼到處散亂,在分層設(shè)計(jì)的方式下,可以將真實(shí)的數(shù)據(jù)接口DataApi和模擬數(shù)據(jù)接口MockDataApi分別作為兩個(gè)數(shù)據(jù)接口的實(shí)現(xiàn)模塊,這樣就可以根據(jù)項(xiàng)目的構(gòu)建類型來(lái)動(dòng)態(tài)提供不同的數(shù)據(jù)接口實(shí)現(xiàn)。

實(shí)現(xiàn)MockDataApi的動(dòng)態(tài)提供的方法也不止一種。一般的java項(xiàng)目可以使用“工廠模式+反射”來(lái)動(dòng)態(tài)提供不同的接口實(shí)現(xiàn)類,再專業(yè)點(diǎn)就是依賴注入——DI框架的使用了。目前gradle是java的最先進(jìn)的構(gòu)建工具,它支持根據(jù)buildType來(lái)分別指定不同的代碼資源,或不同的依賴。可以在一個(gè)單獨(dú)的類庫(kù)module(就是maven中的項(xiàng)目)中來(lái)編寫(xiě)各種MockDataApi的實(shí)現(xiàn)類,然后主app module在debug構(gòu)建時(shí)添加對(duì)它的依賴,此時(shí)數(shù)據(jù)接口的提供者DataApiManager可以向UI層返回這些mock類型的實(shí)例。

為了讓“正常邏輯代碼”和mock相關(guān)代碼的關(guān)聯(lián)盡量少,可以提供一個(gè)MockApiManager來(lái)唯一獲取各個(gè)MockDataApi的實(shí)例。然后在debug構(gòu)建下的MockApiManager會(huì)返回提供了mock實(shí)現(xiàn)的數(shù)據(jù)接口實(shí)例,而release構(gòu)建時(shí)MockApiManager會(huì)一律返null。

不同請(qǐng)求結(jié)果的模擬

MockApi在多次請(qǐng)求時(shí)提供不同的網(wǎng)絡(luò)請(qǐng)求結(jié)果,如服務(wù)器錯(cuò)誤,網(wǎng)絡(luò)錯(cuò)誤,成功等,并模擬出一定的網(wǎng)絡(luò)延遲,這樣就很好的滿足了UI層代碼的各種測(cè)試需求。

為了達(dá)到上述目標(biāo),定義一個(gè)接口IMockApiStrategy來(lái)表示對(duì)數(shù)據(jù)請(qǐng)求的響應(yīng)策略,它定義了方法onResponse(int callCount)。根據(jù)當(dāng)前請(qǐng)求的次數(shù)callCount,onResponse()會(huì)得到不同的模擬響應(yīng)結(jié)果。很明顯,可以根據(jù)測(cè)試需要提供不同的請(qǐng)求響應(yīng)策略,比如不斷返回成功請(qǐng)求,或者不斷返回錯(cuò)誤請(qǐng)求,或輪流返回成功和錯(cuò)誤等。

關(guān)鍵代碼解析

下面就給出各個(gè)部分的關(guān)鍵代碼,來(lái)說(shuō)明以上所描述的MockDataApi模塊的實(shí)現(xiàn)。

UI層代碼

作為示例,界面MainActivity是一個(gè)“任務(wù)列表”的展示。任務(wù)由Task類表示:

public class Task {  public String name;}

界面MainActivity使用一個(gè)TextView來(lái)顯示“加載中、任務(wù)列表、網(wǎng)絡(luò)錯(cuò)誤”等效果,并提供一個(gè)Button來(lái)點(diǎn)擊刷新數(shù)據(jù)。代碼如下:

public class MainActivity extends Activity {    PRivate TextView tv_data;    private boolean requesting = false;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv_data = (TextView) findViewById(R.id.tv_data);        getData();    }    private void getData() {        if (requesting) return;        requesting = true;        ITaskApi api = DataApiManager.ofTask();        if (api != null) {            api.getTasks(new DataApiCallback<List<Task>>() {                @Override                public void onSuccess(List<Task> data) {                    // 顯示數(shù)據(jù)                    StringBuilder sb = new StringBuilder("請(qǐng)求數(shù)據(jù)成功:/n");                    for (int i = 0; i < data.size(); i++) {                        sb.append(data.get(i).name).append("/n");                    }                    tv_data.setText(sb.toString());                    requesting = false;                }                @Override                public void onError(Throwable e) {                    // 顯示錯(cuò)誤                    tv_data.setText("錯(cuò)誤:/n" + e.getMessage());                    requesting = false;                }                @Override                public void onStart() {                    // 顯示loading                    tv_data.setText("正在加載...");                }            });        }    }    public void onRefreshClick(View view) {        getData();    }}

在UI層代碼中,使用DataApiManager.ofTask()獲得數(shù)據(jù)訪問(wèn)接口的實(shí)例。考慮到數(shù)據(jù)請(qǐng)求會(huì)是耗時(shí)的異步操作,這里每個(gè)數(shù)據(jù)接口方法接收一個(gè)DataApiCallback<T> 回調(diào)對(duì)象,T是將返回的數(shù)據(jù)類型。

public interface DataApiCallback<T>  {    void onSuccess(T data);    void onError(Throwable e);    void onStart();}

接口DataApiCallback定義了數(shù)據(jù)接口請(qǐng)求數(shù)據(jù)開(kāi)始和結(jié)束時(shí)的通知。

DataApiManager

根據(jù)分層設(shè)計(jì),UI層和數(shù)據(jù)訪問(wèn)層之間的通信就是基于DataApi接口的,每個(gè)DataApi接口提供一組相關(guān)數(shù)據(jù)的獲取方法。獲取Task數(shù)據(jù)的接口就是ITaskApi:

public interface ITaskApi {    void getTasks(DataApiCallback<List<Task>> callback);}

UI層通過(guò)DataApiManager來(lái)獲得各個(gè)DataApi接口的實(shí)例。也就是在這里,會(huì)根據(jù)當(dāng)前項(xiàng)目構(gòu)建是debug還是release來(lái)選擇性提供MockApi或最終的DataApi。

public class DataApiManager {    private static final boolean MOCK_ENABLE = BuildConfig.DEBUG;    public static ITaskApi ofTask() {        if (MOCK_ENABLE) {            ITaskApi api = MockApiManager.getMockApi(ITaskApi.class);            if (api != null) return api;        }        return new NetTaskApi();    }}

當(dāng)MOCK_ENABLE為true時(shí),會(huì)去MockApiManager檢索一個(gè)所需接口的mock實(shí)例,如果沒(méi)找到,會(huì)返回真實(shí)的數(shù)據(jù)接口的實(shí)現(xiàn),上面的NetTaskApi就是。倘若現(xiàn)在服務(wù)器還無(wú)法進(jìn)行聯(lián)合調(diào)試,它的實(shí)現(xiàn)就簡(jiǎn)單的返回一個(gè)服務(wù)器錯(cuò)誤:

public class NetTaskApi implements ITaskApi {    @Override    public void getTasks(DataApiCallback<List<Task>> callback) {        // 暫時(shí)沒(méi)用實(shí)際的數(shù)據(jù)接口實(shí)現(xiàn)        callback.onError(new Exception("數(shù)據(jù)接口未實(shí)現(xiàn)"));    }}

MockApiManager

DataApiManager利用MockApiManager來(lái)獲取數(shù)據(jù)接口的mock實(shí)例。這樣的好處是模擬數(shù)據(jù)接口的相關(guān)類型都被“封閉”起來(lái),僅通過(guò)一個(gè)唯一類型來(lái)獲取已知的DataApi的一種(這里就指mock)實(shí)例。這樣為分離出mock相關(guān)代碼打下了基礎(chǔ)。

在DataApiManager中,獲取數(shù)據(jù)接口實(shí)例時(shí)會(huì)根據(jù)開(kāi)關(guān)變量MOCK_ENABLE判斷是否可以返回mock實(shí)例。僅從功能上看是滿足動(dòng)態(tài)提供MockApi的要求了。不過(guò),為了讓最終release構(gòu)建的apk中不包含多余的mock相關(guān)的代碼,可以利用gradle提供的buildVariant。

buildVariant使用gradle來(lái)構(gòu)建項(xiàng)目時(shí),可以指定不同的buildType,默認(rèn)會(huì)有debug和release兩個(gè)“構(gòu)建類型”。此外,還可以提供productFlavors來(lái)提供不同的“產(chǎn)品類型”,如demo版,專業(yè)版等。每一種productFlavor和一個(gè)buildType組成一個(gè)buildVariant(構(gòu)建變種)。可以為每一個(gè)buildType,buildVariant,或productFlavor指定特定的代碼資源。

這里利用buildType來(lái)為debug和release構(gòu)建分別指定不同的MockApiManager類的實(shí)現(xiàn)。

默認(rèn)的項(xiàng)目代碼是在src/main/java/目錄下,創(chuàng)建目錄/src/debug/java/來(lái)放置只在debug構(gòu)建時(shí)編譯的代碼。在/src/release/java/目錄下放置只在release構(gòu)建時(shí)編譯的代碼。

debug構(gòu)建時(shí)的MockApiManager
public class MockApiManager {    private static final MockApiManager INSTANCE = new MockApiManager();    private HashMap<String, BaseMockApi> mockApis;    private MockApiManager() {}    public static <T> T getMockApi(Class<T> dataApiClass) {        if (dataApiClass == null) return null;        String key = dataApiClass.getName();        try {            T mock = (T) getInstance().mockApis.get(key);            return mock;        } catch (Exception e) {            return null;        }    }    private void initApiTable() {        mockApis = new HashMap<>();        mockApis.put(ITaskApi.class.getName(), new MockTaskApi());    }    private static MockApiManager getInstance() {        if (INSTANCE.mockApis == null) {            synchronized (MockApiManager.class) {                if (INSTANCE.mockApis == null) {                    INSTANCE.initApiTable();                }            }        }        return INSTANCE;    }}

靜態(tài)方法getMockApi()根據(jù)傳遞的接口類型信息從mockApis中獲取可能的mock實(shí)例,mockApis中注冊(cè)了需要mock的那些接口的實(shí)現(xiàn)類對(duì)象。

release構(gòu)建時(shí)的MockApiManager
public class MockApiManager {    public static <T> T getMockApi(Class<T> dataApiClass) {        return null;    }   }

因?yàn)樽罱Krelease構(gòu)建時(shí)是不需要任何mock接口的,所以此時(shí)getMockApi()一律返回null。也沒(méi)有任何和提供mock接口相關(guān)的類型。

通過(guò)為debug和release構(gòu)建提供不同的MockApiManager代碼,就徹底實(shí)現(xiàn)了MockApi代碼的動(dòng)態(tài)添加和移除。

MockApi的實(shí)現(xiàn)

模擬數(shù)據(jù)接口的思路非常簡(jiǎn)單:根據(jù)請(qǐng)求的次數(shù)callCount,運(yùn)行一定的策略來(lái)不斷地返回不同的響應(yīng)結(jié)果。響應(yīng)結(jié)果包括“網(wǎng)絡(luò)錯(cuò)誤、服務(wù)器錯(cuò)誤、成功”三種狀態(tài),而且還提供一定的網(wǎng)絡(luò)時(shí)間延遲的模擬。

IMockApiStrategy

接口IMockApiStrategy的作用就是抽象對(duì)請(qǐng)求返回不同響應(yīng)結(jié)果的策略,響應(yīng)結(jié)果由IMockApiStrategy.Response表示。

public interface IMockApiStrategy {    void onResponse(int callCount, Response out);    /**     * Mock響應(yīng)返回結(jié)果,表示響應(yīng)的狀態(tài)     */    class Response {        public static final int STATE_NETWORK_ERROR = 1;        public static final int STATE_SERVER_ERROR = 2;        public static final int STATE_SUCCESS = 3;        public int state = STATE_SUCCESS;        public int delayMillis = 600;    }}

Response表示的響應(yīng)結(jié)果包含結(jié)果狀態(tài)和延遲時(shí)間。

作為一個(gè)默認(rèn)的實(shí)現(xiàn),WheelApiStrategy類根據(jù)請(qǐng)求次數(shù),不斷返回上述的三種結(jié)果:

public class WheelApiStrategy implements IMockApiStrategy {    @Override    public void onResponse(int callCount, Response out) {        if (out == null) return;        int step = callCount % 10;        switch (step) {            case 0:            case 1:            case 2:            case 3:                out.state = Response.STATE_SUCCESS;                break;            case 4:            case 5:                out.state = Response.STATE_SERVER_ERROR;                break;            case 6:            case 7:                out.state = Response.STATE_SUCCESS;                break;            case 8:            case 9:                out.state = Response.STATE_NETWORK_ERROR;                break;        }        out.delayMillis = 700;    }}

方法onResponse()的參數(shù)out僅僅是為了避免多次創(chuàng)建小對(duì)象,對(duì)應(yīng)debug構(gòu)建,倒也沒(méi)太大意義。

BaseMockApi

針對(duì)每一個(gè)數(shù)據(jù)訪問(wèn)接口,都可以提供一個(gè)mock實(shí)現(xiàn)。比如為接口ITaskApi提供MockTaskApi實(shí)現(xiàn)類。

為了簡(jiǎn)化代碼,抽象基類BaseMockApi完成了大部分公共的邏輯。

public abstract class BaseMockApi {    protected int mCallCount;    private IMockApiStrategy mStrategy;    private Response mResponse = new Response();    public Response onResponse() {        if (mStrategy == null) {            mStrategy = getMockApiStrategy();        }        if (mStrategy != null) {            mStrategy.onResponse(mCallCount, mResponse);            mCallCount++;        }        return mResponse;    }    protected IMockApiStrategy getMockApiStrategy() {        return new WheelApiStrategy();    }    protected void giveErrorResult(final DataApiCallback<?> callback, Response response) {        Action1<Object> onNext = null;        AndroidSchedulers.mainThread().createWorker().schedule(new Action0() {            @Override            public void call() {                callback.onStart();            }        });        switch (response.state) {            case Response.STATE_NETWORK_ERROR:                onNext = new Action1<Object>() {                    @Override                    public void call(Object o) {                        callback.onError(new IOException("mock network error."));                    }                };                break;            case Response.STATE_SERVER_ERROR:                onNext = new Action1<Object>() {                    @Override                    public void call(Object o) {                        callback.onError(new IOException("mock server error."));                    }                };                break;        }        if (onNext != null) {            Observable.just(10086)                    .delay(response.delayMillis, TimeUnit.MILLISECONDS)                    .subscribeOn(Schedulers.io())                    .observeOn(AndroidSchedulers.mainThread())                    .subscribe(onNext);        }    }     public <T> void giveSuccessResult(final Func0<T> dataMethod, final DataApiCallback<T> callback, final Response response) {        AndroidSchedulers.mainThread().createWorker().schedule(new Action0() {            @Override            public void call() {                Observable.create(new Observable.OnSubscribe<T>() {                    @Override                    public void call(Subscriber<? super T> subscriber) {                        Log.d("MOCK", "onNext Thread = " + Thread.currentThread().getName());                        subscriber.onNext(dataMethod.call());                        subscriber.onCompleted();                    }                }).                delay(response.delayMillis, TimeUnit.MILLISECONDS)                .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new ApiSubcriber(callback));            }        });    }    private static class ApiSubcriber<T> extends Subscriber<T> {        private DataApiCallback<T> callback;        public ApiSubcriber(DataApiCallback<T> callback) {            this.callback = callback;        }        @Override        public void onStart() {            callback.onStart();        }        @Override        public void onCompleted() {}        @Override        public void onError(Throwable e) {            callback.onError(e);        }        @Override        public void onNext(T data) {            callback.onSuccess(data);        }    }}

onResponse()方法onResponse()根據(jù)“響應(yīng)策略”來(lái)針對(duì)一次請(qǐng)求返回一個(gè)“響應(yīng)結(jié)果”,默認(rèn)的策略由方法getMockApiStrategy()提供,子類可以重寫(xiě)它提供其它策略。當(dāng)然策略對(duì)象本身也可以作為參數(shù)傳遞(此時(shí)此方法本身也沒(méi)多大意義了)。一個(gè)想法是,每一個(gè)MockApi類都只需要一個(gè)實(shí)例,這樣它的callCount就可以在程序運(yùn)行期間得到保持。此外,大多數(shù)情況下策略對(duì)象只需要一個(gè)就行了——它是無(wú)狀態(tài)的,封裝算法的一個(gè)“函數(shù)對(duì)象”,為了多態(tài),沒(méi)辦法讓它是靜態(tài)方法。

giveErrorResult()此方法用來(lái)執(zhí)行錯(cuò)誤回調(diào),此時(shí)是不需要數(shù)據(jù)的,只需要根據(jù)response來(lái)執(zhí)行一定的延遲,然后返回網(wǎng)絡(luò)錯(cuò)誤或服務(wù)器錯(cuò)誤。注意一定要在main線程上執(zhí)行callback的各個(gè)方法,這里算是一個(gè)約定,方便UI層直接操作一些View對(duì)象。

giveSuccessResult()此方法用來(lái)執(zhí)行成功回調(diào),此時(shí)需要提供數(shù)據(jù),并執(zhí)行response中的delayMillis延遲。參數(shù)dataMethod用來(lái)提供需要的假數(shù)據(jù),這里保證它的執(zhí)行在非main線程中。同樣,callback的方法都在main線程中執(zhí)行。

上面BaseMockApi中的rxjava的一些代碼都非常簡(jiǎn)單,完全可以使用Thread來(lái)實(shí)現(xiàn)。

提供MockTaskApi

作為示例,這里為ITaskApi提供了一個(gè)mock實(shí)現(xiàn)類:

public class MockTaskApi extends BaseMockApi implements ITaskApi {    @Override    public void getTasks(DataApiCallback<List<Task>> callback) {        Response response = onResponse();        if (response.state == Response.STATE_SUCCESS) {            Func0<List<Task>> mockTasks = new Func0<List<Task>>() {                @Override                public List<Task> call() {                    // here to give some mock data, you can get it from a json file —— if there is.                    ArrayList<Task> tasks = new ArrayList<>();                    int start = (mCallCount - 1) * 6;                    for (int i = start; i < start + 6; i++) {                        Task task = new Task();                        task.name = "Task - " + i;                        tasks.add(task);                    }                    return tasks;                }            };            giveSuccessResult(mockTasks, callback, response);        } else {            giveErrorResult(callback, response);        }    }}

它的代碼幾乎不用過(guò)多解釋,使用代碼提供需要的返回?cái)?shù)據(jù)是非常簡(jiǎn)單的——就像你直接在UI層的Activity中寫(xiě)一個(gè)方法來(lái)造假數(shù)據(jù)那樣。

小結(jié)

無(wú)論如何,經(jīng)過(guò)上面的一系列的努力,模擬數(shù)據(jù)接口的代碼已經(jīng)稍具模塊性質(zhì)了,它可以被動(dòng)態(tài)的開(kāi)關(guān),不影響最終的release構(gòu)建,可以為需要測(cè)試的數(shù)據(jù)接口靈活的提供想要的mock實(shí)現(xiàn)。

很值得一提的是,整個(gè)MockApi模塊都是建立在純java代碼上的。這樣從UI層請(qǐng)求到數(shù)據(jù)訪問(wèn)方法的執(zhí)行,都最終是直接的java方法的調(diào)用,這樣可以很容易獲取調(diào)用傳遞的“請(qǐng)求參數(shù)”,這些參數(shù)都是java類。而如果mock是建立在網(wǎng)絡(luò)框架之上的,那么額外的http報(bào)文的解析是必不可少的。僅僅是為了測(cè)試的目的,分層設(shè)計(jì),讓數(shù)據(jù)訪問(wèn)層可以在真實(shí)接口和mock接口間切換,更簡(jiǎn)單直接些。

最后,造假數(shù)據(jù)當(dāng)然也可以是直接讀取json文件這樣的方式來(lái)完成,如果服務(wù)器開(kāi)發(fā)人員有提供這樣的文件的話。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 南皮县| 织金县| 洪江市| 多伦县| 涿州市| 古田县| 保山市| 洛川县| 金川县| 三原县| 盐边县| 普宁市| 肥城市| 博乐市| 河池市| 昭苏县| 温州市| 西昌市| 噶尔县| 永嘉县| 仙游县| 桃源县| 清新县| 安多县| 当涂县| 祁门县| 盘锦市| 宁波市| 界首市| 军事| 西丰县| 日喀则市| 双流县| 包头市| 灵山县| 隆德县| 车致| 额敏县| 鹤峰县| 石首市| 军事|