英文:
What repository will return when object not found in tests
问题
在Junit测试中,当对象未找到时,仓库会返回什么?
我有这样的测试代码:
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public class CouponServiceTestSuite {
private final static String HOME_TEAM = "home team";
private final static String AWAY_TEAM = "away team";
@Autowired
private CouponService couponService;
@MockBean
private CouponRepository couponRepository;
@MockBean
private MatchRepository matchRepository;
@Test
public void shouldThrowException() {
//Given
//When
//Then
Assertions.assertThrows(BetWinnerException.class, () -> couponService.getCoupon(-6L));
}
}
我想要像这样进行模拟:
Mockito.when(couponRepository.findById(ArgumentMatchers.anyLong()).thenReturn(null);
我的服务类如下:
@Slf4j
@RequiredArgsConstructor
@Service
public class CouponService {
private final CouponRepository couponRepository;
private final MatchRepository matchRepository;
private final CouponMapper couponMapper;
public List<CouponDto> getCoupons() {
log.debug("Getting all coupons");
List<Coupon> couponList = couponRepository.findAll();
List<CouponDto> couponDtoList = couponMapper.mapToCouponDtoList(couponList);
log.debug("Return all coupons: {}", couponDtoList);
return couponDtoList;
}
public CouponDto getCoupon(Long couponId) {
log.debug("Getting coupon by id: {}", couponId);
Coupon coupon = couponRepository.findById(couponId).orElseThrow(
() -> new BetWinnerException(BetWinnerException.ERR_COUPON_NOT_FOUND_EXCEPTION)
);
CouponDto couponDto = couponMapper.mapToCouponDto(coupon);
log.debug("Return coupon: {}", couponDto);
return couponDto;
}
// 其他方法...
}
我认为它应该返回null,但当我这样做时,它返回NullPointerException。我的服务在未找到对象时返回BetWinnerException。那么它会返回什么?我应该如何创建这个测试?
像这样的测试可以正常工作,但我不想使用id = -6。我只是想以某种方式模拟它。
英文:
My question is : what repository will return when object not found in
junit tests.
I have test like this :
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public class CouponServiceTestSuite {
private final static String HOME_TEAM = "home team";
private final static String AWAY_TEAM = "away team";
@Autowired
private CouponService couponService;
@MockBean
private CouponRepository couponRepository;
@MockBean
private MatchRepository matchRepository;
@Test
public void shouldThrowException() {
//Given
//When
//Then
Assertions.assertThrows(BetWinnerException.class, () -> couponService.getCoupon(-6L));
I want to mock this like :
Mockito.when(couponRepository.findById(ArgumentMatchers.anyLong()).thenReturn(null);
My service class :
@Slf4j
@RequiredArgsConstructor
@Service
public class CouponService {
private final CouponRepository couponRepository;
private final MatchRepository matchRepository;
private final CouponMapper couponMapper;
public List<CouponDto> getCoupons() {
log.debug("Getting all coupons");
List<Coupon> couponList = couponRepository.findAll();
List<CouponDto> couponDtoList = couponMapper.mapToCouponDtoList(couponList);
log.debug("Return all coupons: {}", couponDtoList);
return couponDtoList;
}
public CouponDto getCoupon(Long couponId) {
log.debug("Getting coupon by id: {}", couponId);
Coupon coupon = couponRepository.findById(couponId).orElseThrow(()
-> new BetWinnerException(BetWinnerException.ERR_COUPON_NOT_FOUND_EXCEPTION));
CouponDto couponDto = couponMapper.mapToCouponDto(coupon);
log.debug("Return coupon: {}", couponDto);
return couponDto;
}
public CouponDto createCoupon() {
log.debug("Creating new coupon");
Coupon coupon = couponRepository.save(new Coupon());
CouponDto couponDto = couponMapper.mapToCouponDto(coupon);
log.debug("Return created coupon: {}", couponDto);
return couponDto;
}
public CouponDto addMatch(Long couponId, Long matchId) {
log.debug("Add match to the coupon: {}{}", matchId, couponId);
Coupon coupon = couponRepository.findById(couponId).orElseThrow(()
-> new BetWinnerException(BetWinnerException.ERR_COUPON_NOT_FOUND_EXCEPTION));
Match match = matchRepository.findById(matchId).orElseThrow(()
-> new BetWinnerException(BetWinnerException.ERR_MATCH_NOT_FOUND_EXCEPTION));
coupon.getMatchList().add(match);
Coupon updatedCoupon = couponRepository.save(coupon);
CouponDto couponDto = couponMapper.mapToCouponDto(updatedCoupon);
log.debug("Return coupon with added match: {}", couponDto);
return couponDto;
}
public boolean deleteCoupon(Long couponId) {
log.debug("Deleting coupon id: {}", couponId);
couponRepository.deleteById(couponId);
if (couponRepository.existsById(couponId)) {
log.debug("Coupon not deleted id: {}", couponId);
return false;
} else {
log.debug("Coupon deleted id: {}", couponId);
return true;
}
}
}
I thought that it returns null but when i do like this it returns NullPointerException. My service returns BetWinnerException when object is not found.
So what it will return ? How should i create this test ?
Test like this works properly but i dont want to use id = -6. I just want to mock it somehow.
答案1
得分: 0
请在你声明的测试中,将@InjectMocks注解添加到@Service上的@Autowired之上,看看是否解决了问题。但是考虑到你在Service中将Repo声明为FINAL,我不认为它会起作用。如果它不是FINAL且被@Autowired注解,那么@InjectMocks将对你的模拟对象正常工作。但如果你真的需要将它声明为FINAL,请尝试这个链接中的方法:
https://www.baeldung.com/mockito-final
英文:
Please post your entire test class
Add @InjectMocks annotation above the @Autowired in the service you declared in your test and see if it solves the problem, however I don't think it will work considering you have your Repo declared as FINAL in your Service. If it`s not FINAL and is @Autowired, the InjectMocks would work fine for your mock. But if you really need this as FINAL, try this:
答案2
得分: 0
你正在嘲笑couponRepository
,但在使用couponService
,由于没有显示代码来初始化它,很难确定问题出在哪里。
现在你更新了问题,答案显而易见:
- 在服务中,代码期望
couponRepository.findById()
返回一个Optional
,以便在其为空时抛出异常。 - 被嘲笑的bean是普通的
Mockito
模拟,试图返回一个有用的结果;对于集合来说,这是一个空集合,对于对象来说,通常是null。 - 我了解到Mockito 2将支持你期望的功能:https://www.baeldung.com/mockito-2-java-8#return-default-values-for-optional-and-stream
- 这篇文章还展示了如何使Mockito 1返回空的
Optional
。 - 你尝试让它返回
null
,但实际上你需要使用Optional.empty()
。
还是我误解了你实际测试的方式和问题是什么?
- 你是否像我理解的那样在服务中得到了
NullPointerException
? - 还是你已经在使用Mockito 2,并且有其他问题?
英文:
You are mocking couponRepository
but using couponService
and as there is no code shown how that is initialised in your test, it is hard to tell, where the problem is.
Now that you updated your question, the answer is quite obvious:
- in the service the code expects
couponRepository.findById()
to return anOptional
so that it can throw the exception if that is empty - mocked beans are 'normal'
Mockito
mocks that try to return a useful result; for collection this is an empty collection, for objects this is null - usually - TIL that Mockito 2 will support what you expect: https://www.baeldung.com/mockito-2-java-8#return-default-values-for-optional-and-stream
- this article also shows how to make Mockito 1 return the empty
Optional
- you tried to make it return
null
but you actually needOptional.empty()
Or did I misunderstand how you actually test it and what your problem is?
- Do you get a
NullPointerException
in the service as I understood? - Or do you already use Mockito 2 and have another issue?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论