2014-02-09 3 views
2

Я делаю простую заявку на место с API-интерфейсом Foursquare. В Activity у меня есть кнопка, которая при нажатии делает HTTP GET в AsyncTask для службы, чтобы занять трендовые места вокруг текущего местоположения пользователя. Если GET преуспевает, то к активности добавляется фрагмент, содержащий ListView с результатом.Android-тестирование - как синхронизировать AsyncTask

Я хочу проверить, создан ли Фрагмент после нажатия кнопки. Проблема в том, что AsyncTask работает в другом потоке, и тест заканчивается неудачным утверждением.

Вот код:

public void testBtnFindVenues_clickShouldInstantiateVenueListFragment() { 
    TouchUtils.clickView(this, this.btnFindVenues); 
    assertNotNull("VenueListFragment is null", this.getVenueListFragment()); 
} 

private Fragment getVenueListFragment() { 
    FragmentManager fragmentManager = this.activity 
      .getSupportFragmentManager(); 
    VenueListFragment venueListFragment = (VenueListFragment) fragmentManager 
      .findFragmentByTag(this.activity 
        .getString(R.string.fragment_tag_venue_list)); 

    return venueListFragment; 
} 

Как я могу сделать утверждение будет выполняться после того, как AsyncTask выполняется

EDIT: Вот AsyncTask

protected class HttpGetJsonTask extends AsyncTask<Void, Void, ResponsePair> { 
    private String requestUrl; 
    private IOnSuccess onSuccess; 
    private IOnError onError; 

    public HttpGetJsonTask(String requestUrl) { 
     this.requestUrl = requestUrl; 
    } 

    public void setOnSuccess(IOnSuccess onSuccess) { 
     this.onSuccess = onSuccess; 
    } 

    public void setOnError(IOnError onError) { 
     this.onError = onError; 
    } 

    @Override 
    protected ResponsePair doInBackground(Void... params) { 
     HttpClient client = new DefaultHttpClient(); 
     HttpGet get = new HttpGet(this.requestUrl); 
     get.addHeader("content-type", "application/json"); 

     ResponsePair responsePair = new ResponsePair(); 

     try { 
      HttpResponse response = client.execute(get); 
      String jsonData = HttpRequester.this 
        .getResponseContentAsString(response); 
      int statusCode = response.getStatusLine().getStatusCode(); 

      responsePair.setJsonData(jsonData); 
      responsePair.setStatusCode(statusCode); 

      return responsePair; 
     } catch (ClientProtocolException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return responsePair; 
    } 

    @Override 
    protected void onPostExecute(ResponsePair responsePair) { 
     super.onPostExecute(responsePair); 

     HttpRequester.this.executeEvents(this.onSuccess, this.onError, 
       responsePair); 
    } 
} 

private void executeEvents(IOnSuccess onSuccess, IOnError onError, 
     ResponsePair responsePair) { 
    String jsonData = responsePair.getJsonData(); 
    int statusCode = responsePair.getStatusCode(); 

    if (statusCode/100 == 4 || statusCode/100 == 5 || statusCode == 0) { 
     onError.performAction(jsonData); 
    } else { 
     onSuccess.performAction(jsonData); 
    } 
} 

private String getResponseContentAsString(HttpResponse response) { 
    String stringContent = null; 
    InputStream inputStream = null; 
    InputStreamReader reader = null; 
    BufferedReader bufferedReader = null; 

    try { 
     inputStream = response.getEntity().getContent(); 
     reader = new InputStreamReader(inputStream); 
     bufferedReader = new BufferedReader(reader); 

     StringBuilder stringContentBuilder = new StringBuilder(); 
     String line = bufferedReader.readLine(); 

     while (line != null) { 
      stringContentBuilder.append(line); 
      line = bufferedReader.readLine(); 
     } 

     stringContent = stringContentBuilder.toString(); 
    } catch (IOException ex) { 
     ex.printStackTrace(); 
    } finally { 
     try { 
      bufferedReader.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    return stringContent; 
} 

Вот setUp для кнопки и транзакции из VenueListFragment

private void setUpBtnFindVenues() { 
    this.btnFindVenues = (Button) this.findViewById(R.id.btn_findVenues); 
    this.btnFindVenues.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      if (!NetworkUtils 
        .isNetworkConnectionEnabled(VenueListActivity.this)) { 
       MessageNotifier.displayMessage(VenueListActivity.this, 
         R.string.toast_network_connection_not_found); 

       return; 
      } 

      IOnSuccess onSuccess = new IOnSuccess() { 
       @Override 
       public void performAction(String data) { 
        int index = data.indexOf("{\"venues\""); 

        data = data.substring(index, data.length() - 1); 
        Gson gson = new Gson(); 
        ResponseModel response = gson.fromJson(data, 
          ResponseModel.class); 
        VenueListActivity.this.venues = response.getVenues(); 

        if (VenueListActivity.this.venues.size() == 0) { 
         MessageNotifier.displayMessage(
           VenueListActivity.this, 
           R.string.toast_not_venues_within_radius); 
        } 

        VenueListActivity.this 
          .setUpVenueList(VenueListActivity.this.venues); 
       } 
      }; 

      IOnError onError = new IOnError() { 
       @Override 
       public void performAction(String data) { 
        MessageNotifier.displayMessage(VenueListActivity.this, 
          R.string.toast_problem_on_server); 
       } 
      }; 

      // Get the user's location 
      Location location = VenueListActivity.this.locationTracker 
        .getLocation(); 

      if (location == null) { 
       MessageNotifier.displayMessage(VenueListActivity.this, 
         R.string.toast_location_not_found); 
      } else { 
       // Build the route parameters HashMap 
       Map<String, String> routeParams = new HashMap<String, String>(); 
       double latitude = location.getLatitude(); 
       double longitude = location.getLongitude(); 

       Log.d("denis", "Latitude: " + Double.toString(latitude)); 
       Log.d("denis", "Longitude: " + Double.toString(longitude)); 
       routeParams.put("ll", 
         String.format("%s,%s", latitude, longitude)); 

       int radius = (VenueListActivity.this.seekBarRadius 
         .getProgress() + MIN_RADIUS) * SEEK_BAR_PROGRESS_MULTIPLIER; 
       routeParams.put("radius", Integer.toString(radius)); 

       AppUtils.getData().venues() 
         .getTrendingVenues(routeParams, onSuccess, onError); 
      } 
     } 
    }); 
} 

private void setUpVenueList(List<VenueModel> venues) { 
    Gson gson = new Gson(); 

    Bundle arguments = new Bundle(); 
    arguments.putBoolean(BundleKey.IS_TWO_PANE, this.isTwoPane); 
    arguments.putString(BundleKey.VENUES, gson.toJson(venues)); 

    VenueListFragment fragment = new VenueListFragment(); 
    fragment.setArguments(arguments); 

    FragmentManager fragmentManager = this.getSupportFragmentManager(); 
    FragmentTransaction transaction = fragmentManager.beginTransaction(); 

    transaction.replace(R.id.frameLayout_venueListContainer, fragment, 
      this.getString(R.string.fragment_tag_venue_list)); 

    transaction.commit(); 
} 

Вот метод в DataUnitOfWork

public void getTrendingVenues(Map<String, String> routeParams, 
     IOnSuccess onSuccess, IOnError onError) { 
    if (!routeParams.containsKey("ll")) { 
     throw new IllegalArgumentException("The routeParams Map does not contain the \"ll\" route parameter (it is required)"); 
    } 

    StringBuilder urlBuilder = new StringBuilder(); 
    urlBuilder.append(this.rootUrl); 
    urlBuilder.append(String.format("%s%s", "trending", MainPersister.CLIENT_ROUTE_PARAMS)); 

    Set<String> keys = routeParams.keySet(); 
    for (String key : keys) { 
     urlBuilder.append(String.format("&%s=%s", key, routeParams.get(key))); 
    } 

    HttpGetJsonTask get = new HttpGetJsonTask(urlBuilder.toString()); 
    get.setOnSuccess(onSuccess); 
    get.setOnError(onError); 

    get.execute(); 
} 
+0

Я не знаю, для чего вам нужно утверждение. У меня складывается впечатление, что то, что вы хотите выполнить, больше связано с жизненным циклом фрагментов, чем с асинтезной. –

+0

Ну, есть ли способ проверить Фрагмент? Я просто хочу проверить, правильно ли добавлен фрагмент в действие. –

+0

Вы можете принять это как должное. Когда действие создает фрагмент и запрашивает его поместить в контейнер, вам не нужно проверять, удалось ли это сделать. Внутри фрагмента, чтобы начать заполнять данные, например, поместите код в методы onStart или onResume. Таким образом, он начнет свое поведение, когда он будет правильно активирован. –

ответ

1

doInBackground работает на другом потоке, но onPostExecute работает на вызывающем потоке. Убедитесь, что код, который заполняет пользовательский интерфейс после AsyncTask, находится в методе onPostExecute.

+0

У меня есть обработчик событий OnSuccess, который выполняется в onPostExecute(). Дело в том, что тест заканчивается до того, как фактически выполняется метод onPostExecute(). –

+0

давайте посмотрим ваш асинтезный код, пожалуйста, –

+0

Я отредактировал вопрос. Я думаю, что это весь код, который вам нужен –

Смежные вопросы