001package edu.pdx.cs.joy.di;
002
003import org.junit.jupiter.api.Test;
004
005import java.util.Collections;
006
007import static org.junit.jupiter.api.Assertions.assertEquals;
008import static org.junit.jupiter.api.Assertions.assertNotNull;
009import static org.mockito.Mockito.*;
010
011/**
012 * Demonstrates how dependency injection makes it easier to test a {@link BookStore}
013 */
014public class BookStoreTest
015{
016    /**
017     * Tests that a purchased book is removed from the {@link BookInventory} when it is purchased
018     */
019    @Test
020    public void testBookIsPurchased() {
021        final Book testBook = new Book("title", "author", 1.00d);
022        final Book[] removedBook = new Book[1];
023        BookInventory inventory = new MockBookInventory() {
024            @Override
025            public void remove( Book book )
026            {
027                removedBook[0] = book;
028            }
029        };
030        CreditCardService cardService = new MockCreditCardService() {
031            @Override
032            public CreditTransactionCode debit( CreditCard card, double amount )
033            {
034                return CreditTransactionCode.SUCCESS;
035            }
036        };
037        BookStore store = new BookStore(inventory, cardService);
038        CreditCard card = new CreditCard( "123" );
039        double total = store.purchase( Collections.singletonList(testBook), card );
040        assertEquals( testBook.getPrice(), total, 0.0d );
041
042        final Book removed = removedBook[0];
043        assertNotNull( removed );
044        assertEquals(testBook.getTitle(), removed.getTitle());
045        assertEquals(testBook.getAuthor(), removed.getAuthor());
046        assertEquals(testBook.getPrice(), removed.getPrice(), 0.0d);
047    }
048
049    /**
050     * Tests that the credit card is indeed passed to the {@link CreditCardService}
051     */
052    @Test
053    public void testCreditCardIsCharged() {
054        Book book = mock(Book.class);
055        double price = 1.00d;
056        when( book.getPrice() ).thenReturn( price );
057
058        BookInventory inventory = mock(BookInventory.class);
059
060        CreditCardService cardService = mock(CreditCardService.class);
061        when(cardService.debit(any( CreditCard.class ), anyDouble() )).thenReturn( CreditTransactionCode.SUCCESS );
062
063        BookStore store = new BookStore(inventory, cardService);
064
065        CreditCard card = mock(CreditCard.class);
066
067        double total = store.purchase( Collections.singletonList(book), card );
068        assertEquals( book.getPrice(), total, 0.0d );
069
070        verify( cardService ).debit( card, price );      
071    }
072}