webentwicklung-frage-antwort-db.com.de

Unit-Tests mit Android-Volley

Ich würde gerne wissen, wie ich Unit-Tests für das Volley-Framework erstellen kann. Verspotten Sie die Anfragen, die Antworten, damit ich Unit-Tests erstellen kann, für die kein Webservice erforderlich ist, und Netzwerkzugriffe.

Ich habe es gegoogelt, aber ich finde nicht viele Informationen über das Framework

37
apinho

Ich habe eine Unterklasse von HttpStack named FakeHttpStack implementiert, die den gefälschten Antwortkörper aus der lokalen Datei in res/raw lädt. Ich habe dies zu Entwicklungszwecken getan, d. H. Ich kann etwas für eine neue API entwickeln, bevor der Server fertig ist, aber Sie können hier etwas lernen (z. B. HttpStack # peformRequest und createEntity überschreiben).

/**
 * Fake {@link HttpStack} that returns the fake content using resource file in res/raw.
 */
class FakeHttpStack implements HttpStack {
    private static final String DEFAULT_STRING_RESPONSE = "Hello";
    private static final String DEFAULT_JSON_RESPONSE = " {\"a\":1,\"b\":2,\"c\":3}";
    private static final String URL_PREFIX = "http://example.com/";
    private static final String LOGGER_TAG = "STACK_OVER_FLOW";

    private static final int SIMULATED_DELAY_MS = 500;
    private final Context context;

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

    @Override
    public HttpResponse performRequest(Request<?> request, Map<String, String> stringStringMap)
            throws IOException, AuthFailureError {
        try {
            Thread.sleep(SIMULATED_DELAY_MS);
        } catch (InterruptedException e) {
        }
        HttpResponse response
                = new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "OK"));
        List<Header> headers = defaultHeaders();
        response.setHeaders(headers.toArray(new Header[0]));
        response.setLocale(Locale.JAPAN);
        response.setEntity(createEntity(request));
        return response;
    }

    private List<Header> defaultHeaders() {
        DateFormat dateFormat = new SimpleDateFormat("EEE, dd mmm yyyy HH:mm:ss zzz");
        return Lists.<Header>newArrayList(
                new BasicHeader("Date", dateFormat.format(new Date())),
                new BasicHeader("Server",
                        /* Data below is header info of my server */
                        "Apache/1.3.42 (Unix) mod_ssl/2.8.31 OpenSSL/0.9.8e")
        );
    }

    /**
     * returns the fake content using resource file in res/raw. fake_res_foo.txt is used for
     * request to http://example.com/foo
     */
    private HttpEntity createEntity(Request request) throws UnsupportedEncodingException {
        String resourceName = constructFakeResponseFileName(request);
        int resourceId = context.getResources().getIdentifier(
                resourceName, "raw", context.getApplicationContext().getPackageName());
        if (resourceId == 0) {
            Log.w(LOGGER_TAG, "No fake file named " + resourceName
                    + " found. default fake response should be used.");
        } else {
            InputStream stream = context.getResources().openRawResource(resourceId);
            try {
                String string = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
                return new StringEntity(string);
            } catch (IOException e) {
                Log.e(LOGGER_TAG, "error reading " + resourceName, e);
            }
        }

        // Return default value since no fake file exists for given URL.
        if (request instanceof StringRequest) {
            return new StringEntity(DEFAULT_STRING_RESPONSE);
        }
        return new StringEntity(DEFAULT_JSON_RESPONSE);
    }

    /**
     * Map request URL to fake file name
     */
    private String constructFakeResponseFileName(Request request) {
        String reqUrl = request.getUrl();
        String apiName = reqUrl.substring(URL_PREFIX.length());
        return "fake_res_" + apiName;
    }
}

Um FakeHttpStack zu verwenden, müssen Sie es nur an Ihre RequestQueue übergeben. Ich überschreibe auch RequestQueue.

public class FakeRequestQueue extends RequestQueue {
    public FakeRequestQueue(Context context) {
        super(new NoCache(), new BasicNetwork(new FakeHttpStack(context)));
    }
}

Ein guter Punkt für diesen Ansatz ist, dass er nicht viel an Ihrem Code ändern muss. Sie müssen lediglich Ihre RequestQueue auf FakeRequestQueue umstellen, wenn Sie testen. Somit kann es bei Abnahmeprüfungen oder Systemprüfungen verwendet werden.

Auf der anderen Seite könnte es beim Komponententest einen kompakteren Weg geben. Zum Beispiel können Sie Ihre Request.Listener -Unterklasse als separate Klasse implementieren, sodass die onResponse-Methode problemlos getestet werden kann. Ich empfehle Ihnen, mehr Details über das, was Sie testen möchten, oder ein Codefragment hinzuzufügen.

22
Kazuki

Werfen Sie einen Blick auf Volley Tests Ordner, dort finden Sie Beispiele.

MockCache.Java
MockHttpClient.Java
MockHttpStack.Java
MockHttpURLConnection.Java
MockNetwork.Java
MockRequest.Java
MockResponseDelivery.Java
8
Dmytro Danylyk

Nicht ganz sicher, dass ich verstehe, was Sie tun möchten, aber wenn ich es tue, dann hilft Ihnen easymock (eine Bibliothek, in der Mock-Klassen erstellt werden können, die Sie anrufen und vorgegebene Antworten erhalten können). Ein Kerl namens Lars Vogel hat einen schönen Artikel zu diesem Thema, den ich vor einiger Zeit als nützlich empfunden habe.

http://www.vogella.com/articles/EasyMock/article.html

0
erbsman

Hier ist ein Exemplar von des aktuellen Volley-MockHttpStack , das von @Dmytro erwähnt wird

package com.Android.volley.mock;
import com.Android.volley.AuthFailureError;
import com.Android.volley.Request;
import com.Android.volley.toolbox.HttpStack;
import org.Apache.http.HttpResponse;
import Java.io.IOException;
import Java.util.HashMap;
import Java.util.Map;
public class MockHttpStack implements HttpStack {
    private HttpResponse mResponseToReturn;
    private IOException mExceptionToThrow;
    private String mLastUrl;
    private Map<String, String> mLastHeaders;
    private byte[] mLastPostBody;
    public String getLastUrl() {
        return mLastUrl;
    }
    public Map<String, String> getLastHeaders() {
        return mLastHeaders;
    }
    public byte[] getLastPostBody() {
        return mLastPostBody;
    }
    public void setResponseToReturn(HttpResponse response) {
        mResponseToReturn = response;
    }
    public void setExceptionToThrow(IOException exception) {
        mExceptionToThrow = exception;
    }
    @Override
    public HttpResponse performRequest(Request<?> request, Map<String, String> additionalHeaders)
            throws IOException, AuthFailureError {
        if (mExceptionToThrow != null) {
            throw mExceptionToThrow;
        }
        mLastUrl = request.getUrl();
        mLastHeaders = new HashMap<String, String>();
        if (request.getHeaders() != null) {
            mLastHeaders.putAll(request.getHeaders());
        }
        if (additionalHeaders != null) {
            mLastHeaders.putAll(additionalHeaders);
        }
        try {
            mLastPostBody = request.getBody();
        } catch (AuthFailureError e) {
            mLastPostBody = null;
        }
        return mResponseToReturn;
    }
}
0
serv-inc