1

I want to write Unit tests of guice modules in order to verify the bindings. The simplest way to do that is to create an injector and verify the types of returned instances.

The problem with this approach are those implementation classes with side-effects.

Is there a way to test which types are bound in a Guice module without actually creating the instances ?

OGrandeDiEnne
  • 872
  • 7
  • 14
  • related and interesting: http://stackoverflow.com/questions/2448013/how-test-guice-injections – OGrandeDiEnne Jun 12 '13 at 16:08
  • What do you mean, with side effects? Guice encourages an approach when dependencies are injected in constructor, so injection itself cannot cause side-effects. So just calling `getInstance()` on injector won't cause any side effects, and you can easily test the types of the objects. – Vladimir Matveev Jun 13 '13 at 06:04
  • 1
    However, if you *really* need to test types which are bound in modules without actually instantiating them then you can use `Injector.getBindings()` method, which returns whole list of configured bindings. But using it is not very convenient. – Vladimir Matveev Jun 13 '13 at 06:06
  • Generally speaking, it's bad practice to put much of anything in the constructor aside from variable initialization, for both ease of testing and more-predictable performance. Put your side effects in methods instead. See also [this article](http://www.beaconhill.com/solutions/kb/java/code-in-constructor-anti-pattern.html). – Jeff Bowman Jun 18 '13 at 11:56
  • I agree with you Jeff. Unfortunately in the reality you often use other people's classes which may be not follow the best patterns :/ . Anyway, being able to verify the bindings w/o actual instantiation can also be much faster. – OGrandeDiEnne Jul 04 '13 at 09:27

1 Answers1

2

The problem could be addressed using Element SPI. Subclass the DefaultElementVisitor and write the implementation for visiting the Bindings you need to test. For e.g.

public class MyElementVisitor extends DefaultElementVisitor<Void>{

  @Override
  public <String> Void visit(Binding<String> binding) {
      Key<String> key = binding.getKey();
      System.out.println("Key :" + key.getTypeLiteral());
      System.out.println("Annotation : " + key.getAnnotation());
      System.out.println("Source : " + binding.getSource());
      return visitOther(binding);
  }

}

Test code could be written in the visit(...) method. Such bindings which are termed as Module Bindings(hence are open to manipulation), are incomplete.The reason is there is no implementation present to be injected. To visit these bindings we need to iterate over modules we intend to visit. Prepare a list of modules and pass the reference to it as the second argument to Elements.getElements().

    MyElementVisitor defaultElementVisitor = new MyElementVisitor();
    for(Element element : Elements.getElements(Stage.DEVELOPMENT,modules)){
        element.acceptVisitor(defaultElementVisitor);
    }

Advantage to this method is that you do not need to prepare Injector for analysis.