2015-01-07 186 views
1

我想用Mockito測試一些服務,但是當我測試的主類和我注入Mock的地方調用super時,我遇到了問題。 我使用spring運行該項目,這些是我遵循的步驟來獲取錯誤。用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該方法縮短服務,這是一個我想與前面的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。在第二個方法(createAndSaveIfValid)中保存(su),它永遠不會進入方法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創建的模擬。模擬不是具有已知值和方法的真實對象。它是一個與聲明類型具有相同接口的對象,但您可以控制其行爲。默認情況下,模擬對象方法什麼也不做(例如返回null)。因此,如果ShortURLRepository被模擬並注入UrlShortenerControllerWithLogs,則在注入的ShortURLRepository中調用save並不像您期望的那樣調用真實代碼,它什麼也不做。如果您想模擬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; 
    } 
});