views:

61

answers:

3

I would like a JUnit 4 test class to implement the same interface as the class its testing. This way, as the interface changes (and it will, we're in early development), the compiler guarantees that corresponding methods are added to the test class. For example:

public interface Service {
  public String getFoo();
  public String getBar();
}

public class ServiceImpl implements Service {
  @Override public String getFoo() { return "FOO"; }
  @Override public String getBar() { return "BAR"; }
}

public class ServiceTest implements Service {
  @Override
  @Test
  public String getFoo() {
    //test stuff
  }

  @Override
  @Test
  public String getBar() {
    //test stuff
  }
}

When I try this, I get an error: "java.lang.Exception: Method getFoo() should be void", presumably because test methods must return void. Anybody know of any way around this?

A: 

I've been using JUnit 4 for several years and I don't know of a way to do what you want without somehow deriving the JUnit test class from the class to be tested.

Steve Emmerson
+2  A: 

I have to admit, it is a neat trick, though it doesn't scale well to multiple test scenarios.

Anyways, you can use custom runner. For example:

@RunWith(CustomRunner.class)
public class AppTest {

  @Test
  public int testApp() {
    return 0;
  }
}

public class CustomRunner extends JUnit4ClassRunner {

  public CustomRunner(Class<?> klass) throws InitializationError {
    super(klass);
  }

  protected void validate() throws InitializationError {
    // ignore
  }
}
Eugene Kuleshov
Nice! Thats exactly what I'm looking for. No check yet because I haven't quite gotten it to work. At least not yet... Its complaining that "Custom runner class CustomRunner should have a public constructor with signature CustomRunner(Class testClass)". But it does.... So I'm poking around a bit to try to get it working. Stay tuned...
romacafe
Did you put the CustomRunner class into a separate file? I run this example in my IDE before posting here.
Eugene Kuleshov
That did the trick, thanks. Now there is an issue with methods that take a parameter, due to reflection, but thats a different issue. Thanks much!
romacafe
You are welcome. For method with parameter it would be interesting to explore parametrized test runner. But I agree, it is a different question.
Eugene Kuleshov
Great! But 'extends BlockJUnit4ClassRunner' would be better, as JUnit4ClassRunner has been @Deprecated.
卢声远 Shengyuan Lu
+1  A: 

A more natural way would probably be to use a code coverage tool, such as Cobertura. It integrates with JUnit nicely AND it shows you cases where your tests may be deficient in some cases (there are many cases such a tool won't catch though).

TofuBeer