20

So, Guava has simple yet useful Preconditions to check method arguments. But I guess it would be reasonable to have a "Postconditions" class too. Or is it just because java provides assertions?

Since a class like this doesn't exist, what is the "best" (practice) alternative way to check postonditions before a mathod returns?

sebkur
  • 658
  • 2
  • 9
  • 18
Flo
  • 1,367
  • 1
  • 13
  • 27

3 Answers3

17

Testing post conditions would be superfluous . The way we test post-conditions in java is by unit testing.

With unit testing, we make sure that for a given input we get predictable output. With Preconditions, we can verify that we have valid input, and hence the output is already guaranteed by the tests.

Johan Sjöberg
  • 47,929
  • 21
  • 130
  • 148
  • 1
    Unit testing serves mainly public interface testing. So testing private methods for example wouldn't be so "convenient". In that case I guess some form of postcondition would come handy. As it seems I have to use native java "assert". – Flo Oct 20 '12 at 20:28
  • 1
    One question is *if* you [should](http://stackoverflow.com/questions/3299405/how-should-i-test-private-methods-in-java#answer-3299443) test `private` methods in the first place. One option is to change the visibility, e.g., using `protected`. – Johan Sjöberg Oct 20 '12 at 20:30
  • I've had this discussion before http://programmers.stackexchange.com/questions/153350/are-too-many-assertions-code-smell – Flo Oct 20 '12 at 20:32
  • I am not in favour of changing visibility to unit test. I personally use reflection to test whatever I feel needs testing without changing the code. – Eric Tobias Oct 01 '13 at 07:49
15

I would use the Java assert keyword within the method itself to encode the postcondition.

Unit Test or Postcondition?

Unit tests and postconditions serve different purposes.

An assertion in a unit test provides a check on the result of a method for one input vector. It is an oracle specifying the expected outcome for one specific case.

An assert in the method itself verifies that for any input the postcondition holds. It is an oracle specifying (properties of) the expected outcome for all possible cases. Such a postcondition-as-oracle combines well with automated testing techniques in which it is easy to generate inputs, but hard to generate the expected value for each input.

Guava Postconditions?

As to why Guava has a Precondition class, but no Postcondition class, here's my understanding.

Guava Preconditions effectively provides a number of shorthands for common situations in which you'd want to throw a particular kind of exception (Illegal argument, null pointer, index out of bounds, illegal state) based on the method's inputs or the object's state.

For postconditions there are fewer such common cases. Hence there is less need to provide a shorthand throwing specific kinds of exceptions. A failing postcondition is like a HTTP 500 "Internal Server Error" -- all we know something went wrong executing our method.

(Note that Guava's notion of precondition is quite different from that of pure design-by-contract, in which there are no guarantees at all if a precondition is not met -- not even that a reasonable exception is thrown. Guava's Preconditions class provides useful capabilities to make a public API more defensive).

avandeursen
  • 8,458
  • 3
  • 41
  • 51
9

Preconditions and postconditions serve very different purposes.

Preconditions test the input, which is not under the method's control; postconditions test the output, which is. Therefore they make no sense inside the method itself, but only as outside code that tests the method.

However, if you really wanted to put such assertions in your code, the Guava Preconditions would serve pretty well for that, too, even if that is not their intended purpose.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • Guava Preconditions report failures in terms of exceptions telling the client (method user) what that client did wrong (Illegal argument, null pointer, index out of bounds, illegal state). As you say, a failing postcondition, by contrast, is an indication that something went wrong within the method/server. Most likely, that will require different exceptions to be thrown, rendering the use of Guava.Preconditions less useful for checking postconditions. – avandeursen Feb 20 '13 at 20:30