我试图用Mockito测试一些服务,但是当我测试的主类和我注入Mocks的地方调用super时我遇到了问题。 我用spring运行项目,这是我为了得到错误而遵循的步骤。
这是我创建测试的地方
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;
}
}
因此,当我在第二个方法(createAndSaveIfValid)中调用shortURLRepository.save(su)时,它从不进入方法save,因此它返回null而不是我想要的对象。
ShortURLRepository的实现代码和方法save是:
@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 :(得分:0)
这不是错误。这是预期的行为。 @Mock
创建了一个模拟。 @InjectMocks
创建类的实例并注入使用@Mock
创建的模拟。模拟不是具有已知值和方法的真实对象。它是一个与声明类型具有相同接口的对象,但您可以控制其行为。默认情况下,模拟对象方法不执行任何操作(例如,返回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;
}
});