Print
ConversationalVerificationUsingGenerics

The Java 1.4 version of PicoUnit supports a reasonable amount of extensibility, you can add your own types of verification:

interface FrogVerify {
   FrogConstraints that(Frog frog);

   interface FrogConstraints {
     void isGreenEnough();
   }
}

But you cannot add new verifications for existing types, for example the Verify interface has a method for begining a conversation involving Strings:

interface Verify {
  StringConstraints that(String string);
}

Because this method returns a type you cannot control: StringConstraints you cannot add an additional constraint, you can't do this:

verify.that("AbbA").isAPalindrome();

But this is possible in the Java 5 version of PicoUnit, because in version 5 Verify looks like this

interface Verify extends ExtensibleVerify<StringConstraints> {
  StringConstraints that(String string);
}

Verify is just a placeholder for an implementation of ExtensibleVerify hardcoded to return StringConstraints, to add your own constraint, first extend the existing string constraints:

interface CustomStringConstraints extends StringConstraints {
  void isAPalindrome();
}

Next provide your own placeholder verify interface:

interface CustomVerify extends ExtensibleVerify<CustomStringConstraints> {
}

Now we should implement the new constraint:

class CustomStringConstraintsImpl extends StringConstraintsImpl implements CustomStringConstraints {
  public CustomStringConstraintsImpl(Evaluator evaluator) {
    super(evaluator);
  }

  public void isAPalindrom() {
    getEvaluator().evaluate(new StringIsAPalindrome());
  }
}

StringIsAPalindrome is implemented in the same way as FileIsBelowConstraint in 1.4. Now you need to implement the CustomVerify:

class CustomVerifyImpl extends ExtensibleVerifyImpl<CustomStringConstraints> {
  public CustomVerifyImpl(Evaluator evaluator, CustomStringConstraints customStringConstraints) {
    super(evaluator, customStringConstraints);
  }
}

Lastly you need to register the new api:

class CustomVerifyLifecycle extends VerifyLifecycle {
  protected Class verifyType() {
    return CustomVerify.class;
  }

  protected Class verifyImplementationType() {
    return CustomVerifyImpl.class;
  }

  protected Class stringConstraintsType() {
    return CustomStringConstraints.class;
  }
}

Now code that injects CustomVerify can use the original string methods and your additional one:

public void testStringEquality(CustomVerify verify) {
  verify.that("abc").isEqualTo("abc");
}

pubilc void testPalindromes(CustomVerify verify) {
  verify.that("AbbA").isAPalindrome();
}

Actually all of this is a little more simple than reality, in reality ExtensibleVerify and ExtensibleVerifyImpl have many more parametric types, for IntConstraints, ClassConstraints, etc. This just means a few more parameters to pass through.

Powered by Atlassian Confluence