2017-02-21 27 views
1

Я хочу высмеять «источник», когда метод «ProductAdapterService.adapt» вызывается другим классом.Как насмехаться с локальной переменной PowerMockito?

Как это решить? Я действительно пробовал много способов. Пожалуйста, помогите мне. Я новый парень. Спасибо большое!

public class ProductAdapterService { 
private final SearchParameter parameter; 
private List<Festival> festivals; 

public ProductAdapterService(SearchParameter parameter) { 
    this.parameter = parameter; 
} 

public SingleProduct adapt(SearchHit hit, boolean bidding) { 

    //I want to mock "source", I don't want to use "hit.getSource()" 
    Map<String, Object> source = hit.getSource(); 

    SingleProduct sp = new SingleProduct(); 
    sp.setId(TypeConverter.toInt(source.get(FieldName.PRODUCT_ID))); 
    sp.setName(TypeConverter.toString(source.get(FieldName.NAME))); 
    sp.setPrice(this.price(source.get(FieldName.PRICE), source.get(FieldName.PRICE_MAP), source.get(FieldName.FIRST_START_CITIES))); 
    sp.setLevel(TypeConverter.toInt(source.get(FieldName.PRODUCT_LEVEL))); 
    sp.setDepartureCityId(this.departureCity(source.get(FieldName.DEPARTURE_CITY_ID), source.get(FieldName.FIRST_START_CITIES))); 
    sp.setSaleMode(TypeConverter.toString(source.get(FieldName.SALE_MODE))); 
    sp.setBrandName(this.providerBrandName(source.get(FieldName.PROVIDER_BRAND))); 
    sp.setSaleCount(TypeConverter.toInt(source.get(FieldName.MONTHLY_ORDER))); 
    sp.setCommentCount(TypeConverter.toInt(source.get(FieldName.COMMENT_COUNT))); 
    sp.setCommentScore(TypeConverter.toFloat(source.get(FieldName.COMMENT_SCORE))); 
    sp.setBuType(BuType.GT); 
    sp.setType(this.productType(source.get(FieldName.SEARCH_TAB_TYPE_SHOW), sp.getSaleMode())); 
    sp.setSaleout(this.saleout(source.get(FieldName.NON_SALEOUT_CITIES), sp.getDepartureCityId())); 
    if (!sp.isSaleout()) { 
     sp.setFestival(this.festival(source.get(FieldName.FESTIVAL_IDS))); 
    } 
    System.out.println("sp.getName(): " + sp.getName()); 
    return sp; 
}} 

А ниже мой тестовый код:

public class TabSearcherTest0 { 

@Test 
public void test() { 
    SearchParameter parameter = SearchParameter.create(); 
    Ghost.begin(); 
    parameter.getFiltered().setTab(TabType.ALL); 
    parameter.getPoi().setKeyword("Spa"); 
    parameter.getClient().setTrace(TraceMode.MAIN); 

    Map<String, Object> mapMock = new HashMap<String, Object>(); 
    mapMock.put("productgroupid", "12877"); 
    mapMock.put("productid", "5539739"); 
    mapMock.put("firststartcitys", "[1, 2]"); 
    mapMock.put("nonsaleoutcities", "[1, 2]"); 
    mapMock.put("productdiamondlevel", "4"); 
    mapMock.put("commentcount", "0"); 
    mapMock.put("price", "0.0"); 
    mapMock.put("name", "TestName"); 
    mapMock.put("searchtabtypeshow", "1"); 
    mapMock.put("comment", "0.0"); 
    mapMock.put("salemode", "S"); 
    mapMock.put("providerbrandid", "999999"); 
    mapMock.put("departurecityid", "2"); 

    // how to inject the map? 
    // ??? 

    SearchModel model = SearchContext.createContext(parameter).search(); 
    Ghost.end(); 
    System.out.println(model); 

}} 
+0

Где ваш тестовый код? Что вы пытаетесь проверить? – DamCx

+0

Исправить метод 'getSource()' в 'SearchHit'. Я не вижу, чтобы вы использовали 'hit' для чего-нибудь еще. Или просто введите карту непосредственно, а не 'SearchHit'. –

+0

Я добавляю тестовый код, помогите мне – mike

ответ

0

Вы получаете "издевается" неправильный путь. Вы только использовал его, когда вы не может использовать реальную реализацию класса; но вам нужно контролировать, как какой-то объект реагирует на вызовы методов.

Ваш метод тестирования выглядит следующим образом:

public SingleProduct adapt(SearchHit hit, boolean bidding) { 
    //I want to mock "source", I don't want to use "hit.getSource()" 
    Map<String, Object> source = hit.getSource(); 

Неправильно: вы хотите , чтобы убедиться, что hit.getSource() используется. Потому что ваш код использует; и вы пишете свои модульные тесты на текст этот код. Поэтому вы хотите, чтобы ваш производственный код делал свою «нормальную» вещь.

Таким образом, очень просто решение здесь:

@Test 
public void testAdapt() { 
    SearchHit mockedHit = mock(SearchHit.class); 

    Map<String, Object> resonseForGetSource = new HashMap<>(); 
    resonseForGetSource.put("productgroupid", "12877"); 
    ... 

    doReturn(resonseForGetSource).when(mockedHit.getSource()); 

    ProductAdapterService underTest = ... 
    underTest.adapt(mockedHit, true); 
    ... probably some asserts 

или что-то так (не прибить меня на doReturn/когда подробности здесь)

Что вы можете увидеть здесь: ваш производственный код нужна эта карта для выполнения своей работы; поэтому вы просто убедитесь, что такой объект карты отображается в вашем производственном коде.

И в случае, если можно использовать объект real SearchHit (который вы можете настроить с помощью такой карты); то использование этого было бы даже лучше, чем насмешка над этим объектом.

Вы абсолютно стараетесь свести к минимуму ваше использование насмешек. Вы используете его только для получения контроля над объектами, которые используются во время определенного теста.

И помимо этого: вы не знаете о масштабах тестирования вашего устройства. Для того, чтобы тест, что один метод, вам не нужны никакие призраки. Единичный тестовый код, который вы показываете, просто не имеет смысла в контексте класса, который вы показываете нам здесь! Таким образом: вам лучше отступить и внимательно изучить «какие единицы у меня есть» и «как выполнить тестирование именно этого блока X». Вы не набираете текст «X», проверяя «Y»!

+0

Спасибо GhostCat. Я понимаю, что после того, как вы это сказали, я приспособился, я ошибся. – mike