什么仓库会在测试中找不到对象时返回

huangapple go评论71阅读模式
英文:

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 = &quot;home team&quot;;
    private final static String AWAY_TEAM = &quot;away team&quot;;
    @Autowired
    private CouponService couponService;
    @MockBean
    private CouponRepository couponRepository;
    @MockBean
    private MatchRepository matchRepository;
    @Test
    public void shouldThrowException() {
        //Given
        //When
        //Then
        Assertions.assertThrows(BetWinnerException.class, () -&gt; 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&lt;CouponDto&gt; getCoupons() {
        log.debug(&quot;Getting all coupons&quot;);
        List&lt;Coupon&gt; couponList = couponRepository.findAll();
        List&lt;CouponDto&gt; couponDtoList = couponMapper.mapToCouponDtoList(couponList);
        log.debug(&quot;Return all coupons: {}&quot;, couponDtoList);
        return couponDtoList;
    }

    public CouponDto getCoupon(Long couponId) {
        log.debug(&quot;Getting coupon by id: {}&quot;, couponId);
        Coupon coupon = couponRepository.findById(couponId).orElseThrow(()
                -&gt; new BetWinnerException(BetWinnerException.ERR_COUPON_NOT_FOUND_EXCEPTION));
        CouponDto couponDto = couponMapper.mapToCouponDto(coupon);
        log.debug(&quot;Return coupon: {}&quot;, couponDto);
        return couponDto;
    }

    public CouponDto createCoupon() {
        log.debug(&quot;Creating new coupon&quot;);
        Coupon coupon = couponRepository.save(new Coupon());
        CouponDto couponDto = couponMapper.mapToCouponDto(coupon);
        log.debug(&quot;Return created coupon: {}&quot;, couponDto);
        return couponDto;
    }

    public CouponDto addMatch(Long couponId, Long matchId) {
        log.debug(&quot;Add match to the coupon: {}{}&quot;, matchId, couponId);
        Coupon coupon = couponRepository.findById(couponId).orElseThrow(()
                -&gt; new BetWinnerException(BetWinnerException.ERR_COUPON_NOT_FOUND_EXCEPTION));
        Match match = matchRepository.findById(matchId).orElseThrow(()
                -&gt; new BetWinnerException(BetWinnerException.ERR_MATCH_NOT_FOUND_EXCEPTION));
        coupon.getMatchList().add(match);
        Coupon updatedCoupon = couponRepository.save(coupon);
        CouponDto couponDto = couponMapper.mapToCouponDto(updatedCoupon);
        log.debug(&quot;Return coupon with added match: {}&quot;, couponDto);
        return couponDto;
    }

    public boolean deleteCoupon(Long couponId) {
        log.debug(&quot;Deleting coupon id: {}&quot;, couponId);
        couponRepository.deleteById(couponId);
        if (couponRepository.existsById(couponId)) {
            log.debug(&quot;Coupon not deleted id: {}&quot;, couponId);
            return false;
        } else {
            log.debug(&quot;Coupon deleted id: {}&quot;, 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:

https://www.baeldung.com/mockito-final

答案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 an Optional 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 need Optional.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?

huangapple
  • 本文由 发表于 2020年8月5日 03:45:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/63254081.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定