0

Java assert statements are selectively enabled/disabled, based on config flags (eg, -ea). I read online that with JUnit assertions (eg, Assert.assertTrue), you don't need to worry about managing the assertion-config yourself. What exactly does this mean? Either:

1) JUnit assertions (mixed together with Prod code) are never disabled. They behave just like Validate statements, and always get run.

or

2) The JUnit test framework automatically enables all JUnit assertions when running JUnit tests. Whenever the application/code is run outside of JUnit, the JUnit assert methods do nothing at all.

or

3) JUnit assertions are always enabled/disabled by default, but there is a custom config/flag that can be used to disable/enable them

Which of the above is true?

--

Edit: Changed the wording a little bit to clear up any ambiguity.

RvPr
  • 1,074
  • 1
  • 9
  • 26
  • 5
    JUnit tests are never deployed to production (because they are not part of the application), so it doesn't matter. –  Aug 08 '15 at 21:53
  • 3
    JUnit should only be used for unit testing, not in prod – Dici Aug 08 '15 at 21:54
  • 3
    JUnit assertions and Java asserts are too completely different things. JUnit assertions are simple method calls from indide the unit tests. They don't exist in the production code, which doesn't use JUnit. – JB Nizet Aug 08 '15 at 21:54
  • If I'm interpreting correctly, the comments here are saying that JUnit assert statements should only ever be used inside of unit/integration test classes. This conflicts heavily with the advice given in these 2 threads: http://stackoverflow.com/questions/1957645/when-to-use-an-assertion-and-when-to-use-an-exception and http://stackoverflow.com/questions/2966347/assert-vs-junit-assertions . Ie: it's good to have assert statements everywhere in your code, and java asserts can universally be replaced with JUnit asserts. – RvPr Aug 09 '15 at 06:00
  • 1
    @RvPr: IMHO there is no conflict with the SO answers linked above. It's just the term 'assertion' used in different situations. The `assert` keyword is usually used to guard certain functionality (input validation in terms of unexpected input values). Whereas JUnit assertions are used to check the outcome of a certain functionality. – home Aug 09 '15 at 06:17
  • @home You're saying that assert keywords can/should be used in production code, but JUnit assertions shouldn't be. The 2nd link in my comment above indicates that JUnit assertions can be treated as a universal replacement for assert keywords (ie, no one uses assert keywords anymore). Both of these statements cannot simultaneously be true. – RvPr Aug 09 '15 at 12:36
  • 1
    @RvPr: I still do not agree. The second question explicitly focuses on tests whereas you ask about production code. Second, I did not recommend to use `assert` - in fact I try to avoid it... – home Aug 09 '15 at 13:49

2 Answers2

2

This question seems to have opened up a can of worms with regards to coding-guidelines on when to use/not to use asserts. I'll post here the answer to my immediate question regarding whether JUnit Assert statements get disabled. Further down, you will find a discussion on the philosophical aspects of using assertions.


Summary: JUnit assert statements are never disabled, even when running in production with the disable-assertions flag.

Experiment: Created a small main function which throws an error in the very first line. The error was implemented in various different ways. I then ran the application from the command-line like so: mvn clean package; java $JAVA_OPTS -cp ....

  1. Induced error by throwing IllegalArgument exception. Application failed with IllegalArgument exception.

  2. Induced error by adding assert false and ran with assertions enabled (-ea). Application failed.

  3. Induced error by adding assert false and ran with assertions disabled (-da). Application succeeded.

  4. Induced error by adding Assert.assertTrue(false); and ran with assertions enabled (-ea). Application failed with AssertionError.

  5. Induced error by adding Assert.assertTrue(false); and ran with assertions disabled (-da). Application failed with AssertionError.

Did a quick google search to see if there's any way to disable JUnit.Asserts. Didn't find anything. If anyone knows of a way to do so, please let me know, because I believe it's an important distinction.

Conclusion: assert keywords can be enabled/disabled using the -ea commandline flag. JUnit.Asserts cannot be enabled/disabled. If you want to add assertions to your production code, then this becomes a very important distinction. If you want the ability to disable them, use the assert keyword. If you want something that you know will always be enabled, then consider JUnit.Assert, or some other similar framework that throws AssertionErrors.


Regarding the philosophy behind assert usage:

  1. It's good to add assertions of some form to your production code. See: https://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html#usage

Putting Assertions Into Your Code. There are many situations where it is good to use assertions, including: Internal Invariants Control-Flow Invariants Preconditions, Postconditions, and Class Invariants

  1. JUnit Asserts cannot be treated as a universal replacement for java assert keywords. The latter gives you the power to disable them, and the former doesn't. Hence, there is a design choice to be made in choosing which of the 2 to use.

  2. Exceptions and Assertions serve very different purposes and should not be used interchangeably. The following discussion clarifies this further: When to use an assertion and when to use an exception


Related StackOverflow discussions:

assert vs. JUnit Assertions

Community
  • 1
  • 1
RvPr
  • 1,074
  • 1
  • 9
  • 26
  • IMO, your conclusion is wrong. Classes in `*.junit.*` packages should not be used in production code (JUnit is a test framework). In case you want runtime assertions I'd rather use `assert` (which I do not like) or another framework (e.g. http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/util/Assert.html). Of course, one could technically use those classes - as you wrote it is a matter of code conventions / guidelines... – home Aug 09 '15 at 13:47
  • @home Just so we're on the same page: assuming you want an assertion that is never disabled, is there any functional reason not to use JUnit.assert in production? I'm assuming that your objection is philosophical (JUnit classes should only ever be used in tests), and not functional. – RvPr Aug 09 '15 at 13:59
  • @home Besides spring.Assert, is there any other assert-framework that is just as good as JUnit's? Using spring.assert in code not related to Spring seems equally icky for the same reasons as using JUnit.Assert. Using the assert keyword seems like a pain because of it's non-descriptive error messages and lack of functionality that JUnit.Assert offers. – RvPr Aug 09 '15 at 14:01
  • @home Sorry for the many replies! Reading further on SpringFramework.Assert, it doesn't actually throw AssertionErrors, it throws Exceptions. This essentially makes it analogous to a Validate statement, and not analogous to assertions. I think there are important distinctions to be made between exceptions vs assertions, and they shouldn't be used interchangeably. This discussion clarifies that further: http://stackoverflow.com/questions/1957645/when-to-use-an-assertion-and-when-to-use-an-exception – RvPr Aug 09 '15 at 14:07
  • If you want an assertion in production that can never be turned off, just do `throw new AssertionError("message")` – NamshubWriter Aug 09 '15 at 15:04
  • @NamshubWriter What is the advantage of doing that, as opposed to using a JUnit assert statement? JUnit assert statements have many utilities like assertEquals(), assertArraysEqual(), assertNull(), assertNotEmpty() and so on. What's the benefit in abandoning all these utilities and manually throwing AssertionError objects? – RvPr Oct 03 '15 at 20:55
  • @RvPr Having your production code depend on test libraries can make your code harder to maintain and can make your deployment files large – NamshubWriter Oct 03 '15 at 20:57
1

I think you're confused between JUnit assertions and Java's built in assertions.

  1. JUnit assertions are methods that throw an AssertionError exception and should only be used in your test code. JUnit code should not be used in production, only when running your JUnit tests during/between builds. The method names are named like assertEquals( expected, actual) and assertNull(Object) etc. You can't disable these assertions since they are method calls. Also your test code would be pretty useless if you could disable all the JUnit assert methodcalls.

  2. Java's built in assertion is a boolean expression preceded by the assert keyword. If the expression returns false, then it too throws an AssertionError. This kind of assertion can be disabled in production to help speed up your code or turned on to help track down bugs. You can read more about the built in Java assert in the Java Programming Guide

dkatzel
  • 31,188
  • 3
  • 63
  • 67
  • When you say "JUnit assertions should only be used in test code," are you saying that they should only be used inside of unit/integration tests? If so, that seems to conflict heavily with the recommendations given here: http://stackoverflow.com/questions/1957645/when-to-use-an-assertion-and-when-to-use-an-exception Ie, assertions can/should be placed inside your production code, in order to assert that certain code invariants are maintained – RvPr Aug 09 '15 at 05:54
  • @RvPr That question is talking about *Java* assertions, not JUnit assertions. And yes, JUnit is not normally used in production code. JUnit assertions are used for tests. – Matthew Farwell Aug 09 '15 at 07:49
  • @MatthewFarwell Is it your recommendation that we use JUnit Asserts inside of test code, and assert keywords inside of production code? – RvPr Aug 09 '15 at 13:05
  • Yes. Use JUnit assertions in your tests. I personally don't use Java assertions anywhere, but some people do. – Matthew Farwell Aug 09 '15 at 13:36