6

I have a class that take a ArrayList as parameter:

public class Foo {
    private ArrayList<Bar> bars;

    public Foo(ArrayList barList) {
        bars = barList;
    }
}

there is a bug that I can pass any ArrayList into the constructor:

// should compile error with this line
Foo foo = new Foo(new ArrayList<String>());

the problem is if I add this case to test suite, when the bug fixed, I can not compile it. is there anyway to test this case?

weiclin
  • 95
  • 6
  • It's always a good idea to add unit tests for bugs to prevent them from cropping back up again. As you seem to understand yourself, a unit test is not supposed to check for syntax errors, so I wouldn't advise testing for "type correctness" or anything of the kind. That's why there's a compiler. This bug had some unwanted effect in production. How about writing a larger-scale test that uncovers the symptoms of this bug? – prgmtc Jul 13 '15 at 11:29

3 Answers3

3

I don't know of any language/unit test framework that will let you "test" for code that should not compile. If you can't compile it, there is nothing to test. You can however turn on all compiler warnings when building. I'm pretty sure passing an unparameterized collection is a big warning in any JVM after JDK5.

Giovanni Botta
  • 9,626
  • 5
  • 51
  • 94
2

I feel it is bad practise and I don't really see a use for it, but see this example for how to test for compilations errors:

import static org.junit.Assert.assertTrue;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

@RunWith(JUnit4.class)
public class CompileTest {

    //A very naive way checking for any error
    @Test(expected=java.lang.Error.class)
    public void testForError() throws Exception {
        this.is.not.a.statement;
    }

    //An example which check that we only find errors for regarding compilation errors.
    @Test
    public void expectNotCompilableMethod() {
        try {
            uncompilableMethod();
            fail("No compile error detected");
        } catch (Error e) {
            assertTrue("Check for compile error message", e.getMessage().startsWith("Unresolved compilation problems"));
        }
    }

    private void uncompilableMethod() {
        do.bad.things;
    }
}

Edit: 1) I am not sure how this may behave together with build-tools like maven. As far as I know maven breaks the build at compile-errors, so probably the tests will not even be executed.

Denis Lukenich
  • 3,084
  • 1
  • 20
  • 38
  • I build code with gradle, it can not compile, however this is an interesting information, thanks – weiclin Jul 13 '15 at 12:21
0

Fix your method signature:

public Foo(ArrayList<Bar> barList) {
    bars = barList;
}

Problem solved. (You probably also want to check for null.)

Kevin Krumwiede
  • 9,868
  • 4
  • 34
  • 82
  • thanks, but I know how to fix it, my question is how to write unit test for it to prevent same bug happens again – weiclin Jul 13 '15 at 04:41
  • 3
    In that case, Giovanni Botta's suggestion to crank up your compiler warning levels is the correct solution. Unit tests are for testing runtime behavior. They are fundamentally the wrong tool for detecting what should be compiler errors. In fact, parameterized type information is removed before runtime, so it would be impossible for a unit test to detect this before it crashes with a `ClassCastException`. – Kevin Krumwiede Jul 13 '15 at 04:45