A nonsense generator

exercise No. 162


Consider the following String array definitions:

private static final String[] ADJECTIVES = {
      "red",       "green",    "yellow",     "gray",        "solid",   // Index 4
      "fierce",    "friendly", "cowardly",   "convenient",  "foreign", // Index 9
      "national",  "tall",     "short",      "metallic",    "golden",  // Index 14
      "silver",    "sweet",    "nationwide", "competitive", "stable",  // Index 19
      "municipal", "famous" };                                         // Index 21

private static final String[] THINGS = {
      "elephant",   "bowl",    "brick",  "spoon",   "bunny",    // Index 4
      "watermelon", "car",     "cat",    "cup",     "desk",     // Index 9
      "tangerine",  "duck",    "bottle", "road" ,   "fork",     // Index 14
      "physicist",  "griffon", "hat",    "key",     "knife",    // Index 19
      "lawyer",     "llama",   "manual", "meat",    "monitor",  // Index 24
      "mouse",      "dog",     "paper",  "pear",    "pen",      // Index 28
      "pencil",     "phone",   "glass",  "planet",  "potato",   // Index 34
      "engineer",   "salad",   "shoe",   "slipper", "soup",     // Index 39
      "building",   "star",    "steak",  "table",   "terminal", // Index 44
      "treehouse",  "truck",   "cake",   "window" };            // Index 48

private static final String[] VERBS = {
"plans cease fire against", "expected to sell","expected to buy","speaks to","leases",   // Index 4
"signs partnership with",   "advances towards","meets with",     "seen with","sells",    // Index 9
"is authorized to sell",    "signs truce with","converts into",  "buys",     "rents",    // Index 14
"allegedly speaks to",      "collapses on",    "invests on",     "warns",    "threatens",// Index 19
"reported to have met with","now manages",     "starts war with","accuses",  "becomes" , // Index 24
"works together with" };                                                                 // Index 25

Following the build principle The {adjective} {thing} {verb} a {thing}. we may randomly generate nonsense phrases like e.g.:

The red meat now manages a bunny.
The metallic duck works together with a duck.
The competitive bottle signs truce with a treehouse.
The nationwide potato buys a monitor.

Implement an appropriate phrase generator obeying the following guidelines:

  1. Use a random number generator. Test your implementation by a simple main() method.

  2. Your solution should still work when extending the mentioned arrays of verbs, things and adjectives.

  3. Your solution should be testable. But having a random number generator in place effectively defies testability.

    Define an appropriate interface which allows for cheating by replacing a random generator with a (deterministic) sequence generator. The latter will then be used for unit testing allowing for predictable results.

    Thus you effectively mock a random generator by a predictable sequence generator:

    public void testApp() {
       final NonsenseGenerator nonsenseGenerator = new  NonsenseGenerator(
             new PredictableSequenceGenerator(new int[]{
             //adjective thing verb thing
               3,        7,    19,  26, // First sentence fixed index values
               6,        20,   7,   15  // Second sentence fixed index values
       Assert.assertEquals("The gray cat threatens a dog.",
       Assert.assertEquals("The friendly lawyer meets with a physicist.",