예제 #1
0
  @Test
  public void pickFruits() {
    final FruitTree mangoTree = context.mock(FruitTree.class);
    final Mango mango1 = new Mango();
    final Mango mango2 = new Mango();

    context.checking(
        new Expectations() {
          {
            oneOf(mangoTree).pickFruit(with(any(Collection.class)));
            will(
                new VoidAction() {
                  public Object invoke(Invocation invocation) {
                    @SuppressWarnings({"unchecked"})
                    Collection<Fruit> fruits = (Collection<Fruit>) invocation.getParameter(0);
                    fruits.add(mango1);
                    fruits.add(mango2);
                    return null;
                  }
                });
          }
        });

    Collection<Fruit> fruits = new FruitPicker().pickFruits(asList(mangoTree));

    assertEquals(asList(mango1, mango2), fruits);
  }
  @Test
  public void willAnnounceItHasFinishedIfPriceGoesAboveMaximum() {
    context.checking(
        new Expectations() {
          {
            exactly(1).of(listener).sniperFinished(sniper);
          }
        });

    sniper.bidAccepted(unbeatableBid);
  }
  @Test
  public void willLimitBidToMaximum() throws Exception {
    context.checking(
        new Expectations() {
          {
            exactly(1).of(auction).bid(maximumBid);
          }
        });

    sniper.bidAccepted(maximumBid.subtract(new Money(1)));
  }
  @Test
  public void willNotBidPriceGreaterThanMaximum() throws Exception {
    context.checking(
        new Expectations() {
          {
            ignoring(listener);
            never(auction).bid(with(any(Money.class)));
          }
        });

    sniper.bidAccepted(unbeatableBid);
  }
  @Test
  public void triesToBeatTheLatestHighestBid() throws Exception {
    final Money expectedBid = beatableBid.add(increment);

    context.checking(
        new Expectations() {
          {
            oneOf(auction).bid(expectedBid);
          }
        });

    sniper.bidAccepted(beatableBid);
  }
  @Test
  public void catchesExceptionsAndReportsThemToErrorListener() throws Exception {
    final AuctionException exception = new AuctionException("test");

    context.checking(
        new Expectations() {
          {
            allowing(auction).bid(with(any(Money.class)));
            will(throwException(exception));
            exactly(1).of(listener).sniperBidFailed(sniper, exception);
          }
        });

    sniper.bidAccepted(beatableBid);
  }
  @Test
  public void modelBlowsUpInAnUnavoidableWay() throws Exception {
    mockery.checking(
        new Expectations() {
          {
            allowing(browseTransactionsModel).findAllTransactions();
            will(throwException(new InternalStorageException()));
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);

    assertLastToastMatchesRegex(
        "Something strange just happened. Try again. You might need to reinstall the "
            + "application. I feel embarrassed and ashamed.");
  }
  @Test
  public void exportWhateverTheModelProvides() throws Exception {
    final List<Transaction> anyNonEmptyListOfTransactions =
        ObjectMother.anyNonEmptyListOfTransactions();

    mockery.checking(
        new Expectations() {
          {
            allowing(browseTransactionsModel).findAllTransactions();
            will(returnValue(anyNonEmptyListOfTransactions));

            ignoring(androidDevicePublicStorageGateway);

            oneOf(exportAllTransactionsAction).execute(with(anyNonEmptyListOfTransactions));
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);
  }
  @Test
  public void mediaNotAvailable() throws Exception {
    mockery.checking(
        new Expectations() {
          {
            allowing(browseTransactionsModel).findAllTransactions();

            allowing(androidDevicePublicStorageGateway).findPublicExternalStorageDirectory();
            will(throwException(new PublicStorageMediaNotAvailableException()));

            never(exportAllTransactionsAction);
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);

    assertLastToastMatchesRegex(
        "No place to which to export the transactions. Insert an SD card or connect an "
            + "external storage device and try again.");
  }
  @Test
  public void exportActionBlowsUpInAnUnavoidableWay() throws Exception {
    mockery.checking(
        new Expectations() {
          {
            // SMELL How can I ignore these irrelevant details?
            ignoring(browseTransactionsModel);
            ignoring(androidDevicePublicStorageGateway);

            allowing(exportAllTransactionsAction).execute(with(any(List.class)));
            will(throwException(new InternalStorageException()));
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);

    assertLastToastMatchesRegex(
        "Something strange just happened. Try again. You might need to reinstall the "
            + "application. I feel embarrassed and ashamed.");
  }
  @Test
  public void mediaNotWritable() throws Exception {
    mockery.checking(
        new Expectations() {
          {
            allowing(browseTransactionsModel).findAllTransactions();

            allowing(androidDevicePublicStorageGateway).findPublicExternalStorageDirectory();
            will(
                throwException(
                    new PublicStorageMediaNotWritableException(
                        new File("/mnt/sdcard/TrackEveryPenny.csv"))));

            never(exportAllTransactionsAction);
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);

    assertLastToastMatchesRegex(
        "Permission denied trying to export the transactions to file "
            + "/mnt/sdcard/TrackEveryPenny.csv");
  }
  @Test
  public void happyPath() throws Exception {
    final Collection<Object> anyValidNonTrivialCollectionOfTransactions =
        Lists.newArrayList(new Object(), new Object(), new Object());

    mockery.checking(
        new Expectations() {
          {
            allowing(browseTransactionsModel).findAllTransactions();

            will(returnValue(anyValidNonTrivialCollectionOfTransactions));

            // SMELL Irrelevant detail
            ignoring(androidDevicePublicStorageGateway).findPublicExternalStorageDirectory();

            allowing(exportAllTransactionsAction).execute(with(any(List.class)));
            // succeeds by not throwing an exception
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);

    assertLastToastMatchesRegex("Exported all transactions to (.+)\\.csv");
  }
@RunWith(RobolectricTestRunner.class)
public class HandleExportAllTransactionsTest {
  private Mockery mockery = new Mockery();
  private final BrowseTransactionsModel browseTransactionsModel =
      mockery.mock(BrowseTransactionsModel.class);
  private final ExportAllTransactionsAction exportAllTransactionsAction =
      mockery.mock(ExportAllTransactionsAction.class);
  private final AndroidDevicePublicStorageGateway androidDevicePublicStorageGateway =
      mockery.mock(AndroidDevicePublicStorageGateway.class);

  private final BrowseTransactionsActivity browseTransactionsActivity =
      new BrowseTransactionsActivity(
          null,
          exportAllTransactionsAction,
          androidDevicePublicStorageGateway,
          browseTransactionsModel);

  @Before
  public void initializeActivity() {
    browseTransactionsActivity.onCreate(null);
    browseTransactionsActivity.setCollaborators(
        exportAllTransactionsAction, androidDevicePublicStorageGateway, browseTransactionsModel);
  }

  @Test
  public void happyPath() throws Exception {
    final Collection<Object> anyValidNonTrivialCollectionOfTransactions =
        Lists.newArrayList(new Object(), new Object(), new Object());

    mockery.checking(
        new Expectations() {
          {
            allowing(browseTransactionsModel).findAllTransactions();

            will(returnValue(anyValidNonTrivialCollectionOfTransactions));

            // SMELL Irrelevant detail
            ignoring(androidDevicePublicStorageGateway).findPublicExternalStorageDirectory();

            allowing(exportAllTransactionsAction).execute(with(any(List.class)));
            // succeeds by not throwing an exception
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);

    assertLastToastMatchesRegex("Exported all transactions to (.+)\\.csv");
  }

  @Test
  public void mediaNotAvailable() throws Exception {
    mockery.checking(
        new Expectations() {
          {
            allowing(browseTransactionsModel).findAllTransactions();

            allowing(androidDevicePublicStorageGateway).findPublicExternalStorageDirectory();
            will(throwException(new PublicStorageMediaNotAvailableException()));

            never(exportAllTransactionsAction);
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);

    assertLastToastMatchesRegex(
        "No place to which to export the transactions. Insert an SD card or connect an "
            + "external storage device and try again.");
  }

  @Test
  public void mediaNotWritable() throws Exception {
    mockery.checking(
        new Expectations() {
          {
            allowing(browseTransactionsModel).findAllTransactions();

            allowing(androidDevicePublicStorageGateway).findPublicExternalStorageDirectory();
            will(
                throwException(
                    new PublicStorageMediaNotWritableException(
                        new File("/mnt/sdcard/TrackEveryPenny.csv"))));

            never(exportAllTransactionsAction);
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);

    assertLastToastMatchesRegex(
        "Permission denied trying to export the transactions to file "
            + "/mnt/sdcard/TrackEveryPenny.csv");
  }

  @Test
  public void modelBlowsUpInAnUnavoidableWay() throws Exception {
    mockery.checking(
        new Expectations() {
          {
            allowing(browseTransactionsModel).findAllTransactions();
            will(throwException(new InternalStorageException()));
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);

    assertLastToastMatchesRegex(
        "Something strange just happened. Try again. You might need to reinstall the "
            + "application. I feel embarrassed and ashamed.");
  }

  @Test
  public void exportActionBlowsUpInAnUnavoidableWay() throws Exception {
    mockery.checking(
        new Expectations() {
          {
            // SMELL How can I ignore these irrelevant details?
            ignoring(browseTransactionsModel);
            ignoring(androidDevicePublicStorageGateway);

            allowing(exportAllTransactionsAction).execute(with(any(List.class)));
            will(throwException(new InternalStorageException()));
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);

    assertLastToastMatchesRegex(
        "Something strange just happened. Try again. You might need to reinstall the "
            + "application. I feel embarrassed and ashamed.");
  }

  @Test
  public void exportWhateverTheModelProvides() throws Exception {
    final List<Transaction> anyNonEmptyListOfTransactions =
        ObjectMother.anyNonEmptyListOfTransactions();

    mockery.checking(
        new Expectations() {
          {
            allowing(browseTransactionsModel).findAllTransactions();
            will(returnValue(anyNonEmptyListOfTransactions));

            ignoring(androidDevicePublicStorageGateway);

            oneOf(exportAllTransactionsAction).execute(with(anyNonEmptyListOfTransactions));
          }
        });

    pressExportAllTransactionsButton(browseTransactionsActivity);
  }

  private void pressExportAllTransactionsButton(
      BrowseTransactionsActivity browseTransactionsActivity) {
    browseTransactionsActivity.exportAllTransactions(
        browseTransactionsActivity.findViewById(R.id.exportAllTransactionsButton));
  }

  public static void assertLastToastMatchesRegex(String patternText) {
    ShadowHandler.idleMainLooper();
    assertThat(ShadowToast.getTextOfLatestToast(), matches(Pattern.compile(patternText)));
  }
}
/**
 * This and other classes in this package (except, naturally, AuctionSniper_JMockit_Test) are based
 * on the original source code available <a
 * href="http://svn.jmock.codehaus.org/browse/jmock/trunk/jmock2/example/org/jmock/example/sniper">here</a>.
 * Small modifications were made to simplify the code, without compromising the original design.
 */
@RunWith(JMock.class)
public final class AuctionSniperTest {
  final Mockery context = new JUnit4Mockery();

  final Money increment = new Money(2);
  final Money maximumBid = new Money(20);
  final Money beatableBid = new Money(10);
  final Money unbeatableBid = maximumBid.add(new Money(1));

  final Auction auction = context.mock(Auction.class);
  final AuctionSniperListener listener = context.mock(AuctionSniperListener.class, "listener");

  final AuctionSniper sniper = new AuctionSniper(auction, increment, maximumBid, listener);

  @Test
  public void triesToBeatTheLatestHighestBid() throws Exception {
    final Money expectedBid = beatableBid.add(increment);

    context.checking(
        new Expectations() {
          {
            oneOf(auction).bid(expectedBid);
          }
        });

    sniper.bidAccepted(beatableBid);
  }

  @Test
  public void willNotBidPriceGreaterThanMaximum() throws Exception {
    context.checking(
        new Expectations() {
          {
            ignoring(listener);
            never(auction).bid(with(any(Money.class)));
          }
        });

    sniper.bidAccepted(unbeatableBid);
  }

  @Test
  public void willLimitBidToMaximum() throws Exception {
    context.checking(
        new Expectations() {
          {
            exactly(1).of(auction).bid(maximumBid);
          }
        });

    sniper.bidAccepted(maximumBid.subtract(new Money(1)));
  }

  @Test
  public void willAnnounceItHasFinishedIfPriceGoesAboveMaximum() {
    context.checking(
        new Expectations() {
          {
            exactly(1).of(listener).sniperFinished(sniper);
          }
        });

    sniper.bidAccepted(unbeatableBid);
  }

  @Test
  public void catchesExceptionsAndReportsThemToErrorListener() throws Exception {
    final AuctionException exception = new AuctionException("test");

    context.checking(
        new Expectations() {
          {
            allowing(auction).bid(with(any(Money.class)));
            will(throwException(exception));
            exactly(1).of(listener).sniperBidFailed(sniper, exception);
          }
        });

    sniper.bidAccepted(beatableBid);
  }
}