2015-01-07 8 views
1

Я пытаюсь проверить некоторые сервисы с помощью Mockito, но у меня проблемы, когда основной класс, который я тестирую, и где я заказываю Mocks, вызывает супер. Я запускаю проект с помощью пружины, и это шаги, которые я выполняю, чтобы получить ошибку.Тестирование с помощью Mockito

Вот где я создать тестовый

public class UrlShortenerTests { 

private MockMvc mockMvc; 

@Mock 
private ShortURLRepository shortURLRepository; 

@Mock 
private ClickRepository clickRespository; 

@InjectMocks 
private UrlShortenerControllerWithLogs urlShortenerWL; 


@Before 
public void setup() { 
    MockitoAnnotations.initMocks(this); 
    this.mockMvc = MockMvcBuilders.standaloneSetup(urlShortenerWL).build(); 
} 

@Test 
public void thatShortenerCreatesARedirectIfTheURLisOK() throws Exception { 
    mockMvc.perform(post("/link") 
      .param("url", "http://www.google.com")) 
      .andDo(print()) 
      .andExpect(status().isCreated()) 
      .andExpect(jsonPath("$.target", is("http://example.com/"))); 
} 
} 

Вот класс UrlShortenerControllerWithLogs с методом Shortener, который является один я хочу проверить с предыдущего вызова POST

@RestController 
public class UrlShortenerControllerWithLogs extends UrlShortenerController { 

@Autowired 
private ClickRepository clickRepository; 
@Autowired 
private ShortURLRepository SURLR; 

public ResponseEntity<ShortURL> shortener(@RequestParam("url") String url, 
     @RequestParam(value = "sponsor", required = false) String sponsor, 
     @RequestParam(value = "brand", required = false) String brand, 
     HttpServletRequest request) { 

    ResponseEntity<ShortURL> su = super.shortener(url, sponsor, brand, 
      request); 
    return su; 
} 

И это является суперклассом

@RestController 
public class UrlShortenerController { 

@Autowired 
protected ShortURLRepository shortURLRepository; 

@Autowired 
protected ClickRepository clickRepository; 

@RequestMapping(value = "/link", method = RequestMethod.POST) 
public ResponseEntity<ShortURL> shortener(@RequestParam("url") String url, 
     @RequestParam(value = "sponsor", required = false) String sponsor, 
     @RequestParam(value = "brand", required = false) String brand, 
     HttpServletRequest request) { 
    ShortURL su = createAndSaveIfValid(url, sponsor, brand, UUID 
      .randomUUID().toString(), extractIP(request)); 
    if (su != null) { 
     HttpHeaders h = new HttpHeaders(); 
     h.setLocation(su.getUri()); 
     return new ResponseEntity<>(su, h, HttpStatus.CREATED); 
    } else { 
     return new ResponseEntity<>(HttpStatus.BAD_REQUEST); 
    } 
} 

protected ShortURL createAndSaveIfValid(String url, String sponsor, 
     String brand, String owner, String ip) { 
    UrlValidator urlValidator = new UrlValidator(new String[] { "http", 
      "https" }); 
    if (urlValidator.isValid(url)) { 
     String id = Hashing.murmur3_32() 
       .hashString(url, StandardCharsets.UTF_8).toString(); 
     ShortURL su = new ShortURL(id, url, 
       linkTo(
         methodOn(UrlShortenerController.class).redirectTo(
           id, null)).toUri(), sponsor, new Date(
         System.currentTimeMillis()), owner, 
       HttpStatus.TEMPORARY_REDIRECT.value(), true, ip, null); 
     return shortURLRepository.save(su); 
    } else { 
     return null; 
    } 
} 

Итак, когда я зволю в shortURLRepository. save (su) во втором методе (createAndSaveIfValid), он никогда не входит в метод save, поэтому он возвращает мне null вместо объекта, который я хочу.

Код реализации ShortURLRepository и метод экономии является:

@Repository 
public class ShortURLRepositoryImpl implements ShortURLRepository { 

private static final Logger log = LoggerFactory 
     .getLogger(ShortURLRepositoryImpl.class); 
@Override 
public ShortURL save(ShortURL su) { 
    try { 
     jdbc.update("INSERT INTO shorturl VALUES (?,?,?,?,?,?,?,?,?)", 
       su.getHash(), su.getTarget(), su.getSponsor(), 
       su.getCreated(), su.getOwner(), su.getMode(), su.getSafe(), 
       su.getIP(), su.getCountry()); 
    } catch (DuplicateKeyException e) { 
     log.debug("When insert for key " + su.getHash(), e); 
     return su; 
    } catch (Exception e) { 
     log.debug("When insert", e); 
     return null; 
    } 
    return su; 
} 

Я думаю, что проблема заключается в том, что объект ShortURLRepository создан в тестовом классе не инициализируется на супер класс (UrlShortenerController) или что-то похожее.

Возможно ли это? Может ли кто-нибудь мне помочь?

Полный код в: https://github.com/alberto-648702/UrlShortener2014

Класс UrlShortenerTests находится в:

bangladeshGreen/src/test/java/urlshortener2014/bangladeshgreen 

Класс UrlShortenerControllerWithLogs находится в:

bangladeshGreen/src/main/java/urlshortener2014/bangladeshgreen/web 

Класс UrlShortenerController находится в:

common/src/main/java/urlshortener2014/common/web 

Класс ShortURLRepositoryImpl находится в:

common/src/main/java/urlshortener2014/common/repository 

ответ

0

Это не ошибка. Это ожидаемое поведение. @Mock создает макет. @InjectMocks создает экземпляр класса и вводит макеты, созданные с помощью @Mock. Макет не является реальным объектом с известными значениями и методами. Это объект, который имеет тот же интерфейс, что и объявленный тип, но вы контролируете его поведение. По умолчанию методы издевающихся объектов ничего не делают (например, return null). Поэтому, если ShortURLRepository издевается и вводится в UrlShortenerControllerWithLogs, вызывающий save в введенном ShortURLRepository, не вызывает реальный код, как вы ожидали, он ничего не делает. Если вы хотите высмеять поведение save, то добавьте в код setup код:

when(shortURLRepository.save(org.mockito.Matchers.any(ShortURL.class))). 
    then(new Answer<ShortURL>() { 
     @Override 
     public ShortURL answer(InvocationOnMock invocation) throws Throwable { 
      ShortURL su = (ShortURL) invocation.getArguments()[0]; 
      // Do something with su if needed 
      return su; 
    } 
}); 
Смежные вопросы