PurchasingSession extends
        AbstractSession<RecommendedParticipation, ParticipationDescriptor, Participation> { public static Collection<Participation> purchase(final PowerTenant auth, final Collection<ParticipationDescriptor> items, final PurchaseStrategy strategy) { final PurchasingSession s = new PurchasingSession(items, auth); final Collection<ParticipationDescriptor> c = s.getAvailable(); if (c.isEmpty()) { return Collections.emptyList(); } s.tenant.fire(purchasingStartedLazy(() -> purchasingStarted(auth.getPortfolio() .getOverview()))); s.purchase(strategy); final Collection<Participation> result = s.getResult(); s.tenant.fire(purchasingCompletedLazy(() -> purchasingCompleted(result, auth.getPortfolio() .getOverview()))); return Collections.unmodifiableCollection(result); } PurchasingSession(final Collection<ParticipationDescriptor> marketplace, final PowerTenant tenant); static Collection<Participation> purchase(final PowerTenant auth,
            final Collection<ParticipationDescriptor> items,
            final PurchaseStrategy strategy);  }
@Test void empty() { final Zonky z = harmlessZonky(); final PowerTenant auth = mockTenant(z); final Collection<Participation> i = PurchasingSession.purchase(auth, Collections.emptyList(), null); assertThat(i).isEmpty(); }
@Test void properReal() { final Loan l = new MockLoanBuilder() .set(LoanImpl::setAmount, Money.from(200)) .set(LoanImpl::setRating, Rating.D) .set(LoanImpl::setRemainingInvestment, Money.from(200)) .set(LoanImpl::setReservedAmount, Money.from(0)) .set(LoanImpl::setMyInvestment, mockMyInvestment()) .build(); final int loanId = l.getId(); final Participation p = mock(ParticipationImpl.class); doReturn(l.getId()).when(p) .getLoanId(); when(p.getRating()).thenReturn(Rating.D); when(p.getRemainingPrincipal()).thenReturn(Money.from(200)); final PurchaseStrategy s = mock(PurchaseStrategy.class); when(s.recommend(any(), any(), any())).thenAnswer(i -> { final Collection<ParticipationDescriptor> participations = i.getArgument(0); return participations.stream() .map(ParticipationDescriptor::recommend) .flatMap(Optional::stream); }); final Zonky z = harmlessZonky(); when(z.getLoan(eq(loanId))).thenReturn(l); final PowerTenant auth = mockTenant(z, false); final ParticipationDescriptor pd = new ParticipationDescriptor(p, () -> l); final Collection<Participation> i = PurchasingSession.purchase(auth, Collections.singleton(pd), s); assertThat(i).hasSize(1); assertThat(getEventsRequested()).hasSize(4); verify(z).purchase(eq(p)); final RemotePortfolio rp = auth.getPortfolio(); final Rating rating = l.getRating(); verify(rp).simulateCharge(eq(loanId), eq(rating), any()); verify(auth).setKnownBalanceUpperBound(eq(Money.from(Integer.MAX_VALUE - 200))); }
@Test void failure() { final Loan l = new MockLoanBuilder() .set(LoanImpl::setAmount, Money.from(200)) .set(LoanImpl::setRating, Rating.D) .set(LoanImpl::setRemainingInvestment, Money.from(200)) .set(LoanImpl::setReservedAmount, Money.from(0)) .set(LoanImpl::setMyInvestment, mockMyInvestment()) .build(); final Participation p = mock(ParticipationImpl.class); doReturn(l.getId()).when(p) .getLoanId(); when(p.getRemainingPrincipal()).thenReturn(Money.from(200)); final PurchaseStrategy s = mock(PurchaseStrategy.class); when(s.recommend(any(), any(), any())).thenAnswer(i -> { final Collection<ParticipationDescriptor> participations = i.getArgument(0); return participations.stream() .map(ParticipationDescriptor::recommend) .flatMap(Optional::stream); }); final Zonky z = harmlessZonky(); when(z.getLoan(eq(l.getId()))).thenReturn(l); final Response response = Response.status(400) .entity(PurchaseFailureType.INSUFFICIENT_BALANCE.getReason() .get()) .build(); final ClientErrorException thrown = new BadRequestException(response); when(z.purchase(any())).thenReturn(PurchaseResult.failure(thrown)); final PowerTenant auth = mockTenant(z, false); final ParticipationDescriptor pd = new ParticipationDescriptor(p, () -> l); final Collection<Participation> i = PurchasingSession.purchase(auth, Collections.singleton(pd), s); assertThat(i).isEmpty(); assertThat(auth.getKnownBalanceUpperBound()).isEqualTo(Money.from(199)); }
@Test void failureDueToTooManyRequests() { final Loan l = new MockLoanBuilder() .set(LoanImpl::setAmount, Money.from(200)) .set(LoanImpl::setRating, Rating.D) .set(LoanImpl::setRemainingInvestment, Money.from(200)) .set(LoanImpl::setReservedAmount, Money.from(0)) .set(LoanImpl::setMyInvestment, mockMyInvestment()) .build(); final Participation p = mock(ParticipationImpl.class); doReturn(l.getId()).when(p) .getLoanId(); when(p.getRemainingPrincipal()).thenReturn(Money.from(200)); final PurchaseStrategy s = mock(PurchaseStrategy.class); when(s.recommend(any(), any(), any())).thenAnswer(i -> { final Collection<ParticipationDescriptor> participations = i.getArgument(0); return participations.stream() .map(ParticipationDescriptor::recommend) .flatMap(Optional::stream); }); final Zonky z = harmlessZonky(); when(z.getLoan(eq(l.getId()))).thenReturn(l); final Response response = Response.status(400) .entity(PurchaseFailureType.TOO_MANY_REQUESTS.getReason() .get()) .build(); final ClientErrorException thrown = new BadRequestException(response); when(z.purchase(any())).thenReturn(PurchaseResult.failure(thrown)); final PowerTenant auth = mockTenant(z, false); final ParticipationDescriptor pd = new ParticipationDescriptor(p, () -> l); assertThatThrownBy(() -> PurchasingSession.purchase(auth, Collections.singleton(pd), s)) .isInstanceOf(IllegalStateException.class); }