Play 2.4中的Guice,DI和单元测试

Zar*_*tra 12 java unit-testing guice playframework-2.4

所以我一直试图通过文档来解决这个问题,但我没有得到任何结果.

我在一个创建存储库对象的服务类中设置了一些简单的DI绑定.简单.但是,当我在测试模式下运行它时,@ Inject什么都不做,并且从不实例化存储库对象.

@Inject
TagRepository tagRepository;
Run Code Online (Sandbox Code Playgroud)

所以在它使用的行上,在测试模式下,我们当然会得到一个NullPointerException

tagRepository.tagExistsByName(tag);
Run Code Online (Sandbox Code Playgroud)

这样就冒充我的测试了:

[error] Test services.TagsServiceTest.testAddNewTag failed: java.lang.NullPointerException: null, took 0.097 sec
[error]     at services.TagService.tagExists(TagService.java:27)
[error]     at services.TagService.addNewTag(TagService.java:18)
[error]     at services.TagsServiceTest.testAddNewTag(TagsServiceTest.java:29)
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何配置我的应用程序以在测试模式下使用Guice注入器?我的控制器没有这个问题,因为实际上正在向他们发出请求,设置了完整的应用程序.

我应该提到的一件事是我正在使用提供程序来为测试提供我的应用程序.我应该使用Guice应用程序构建器吗?如果是这样,那会去哪儿?在这方面,游戏文档并不是很有用.这是提供者

@Override
protected FakeApplication provideFakeApplication() {
    return new FakeApplication(new java.io.File("."), Helpers.class.getClassLoader(), ImmutableMap.of("play.http.router", "router.Routes"), new ArrayList<String>(), null);
}
Run Code Online (Sandbox Code Playgroud)

更新:

以下是基于以下建议的更新

在我的BaseTest类中

    @Override
    protected Application provideApplication() {
        return new GuiceApplicationBuilder().in(Mode.TEST).build();
    }
Run Code Online (Sandbox Code Playgroud)

然后在服务测试类中

    @Before
    public void beforeTest() {
        Injector injector = new GuiceInjectorBuilder().bindings(bind(TagService.class).toInstance(new TagService())).injector();
        tagService = injector.instanceOf(TagService.class);
    }
Run Code Online (Sandbox Code Playgroud)

但是,我仍然得到空指针异常,因为没有注入TagRepository.

回答:

我在想这个有点不对劲.如果您使用需要注入的对象设置注入器,然后从中创建一个实例,您将不再获得NullPointerExceptions

@Before
public void beforeTest() {
    Injector injector = new GuiceInjectorBuilder().bindings(bind(TagRepository.class).toInstance(new TagRepository())).injector();
    tagService = injector.instanceOf(TagService.class);
}
Run Code Online (Sandbox Code Playgroud)

Ste*_*ner 6

如果您正在扩展WithApplication,则可以覆盖protected Application provideApplication()以返回Application构建的使用GuiceApplicationBuilder.

例如(基于此代码)您可以创建应用程序,添加或覆盖绑定等,并设置模式.如果您使类成为抽象,那么它将自动与所有子类一起使用.

public abstract class AbstractFakeApplicationTest extends WithApplication
{
    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractFakeApplicationTest.class);

    @Override
    protected Application provideApplication()
    {
        return new GuiceApplicationBuilder().in(Mode.TEST)
                                            .build();
    }

    @Override
    public void startPlay()
    {
        super.startPlay();
        // mock or otherwise provide a context
        Http.Context.current.set(new Http.Context(1L,
                                                  Mockito.mock(RequestHeader.class),
                                                  Mockito.mock(Http.Request.class),
                                                  Collections.<String, String>emptyMap(),
                                                  Collections.<String, String>emptyMap(),
                                                  Collections.<String, Object>emptyMap()));
    }

    public Http.Context context()
    {
        return Http.Context.current.get();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,子类只是扩展此类并正常测试 - 所有DI都应该像正常运行应用程序时那样发生.

你可以在这里看到它的各种例子

这给出了您需要做的基本概要.希望https://playframework.com/documentation/2.4.x/JavaTestingWithGuice上的文档现在会更有意义.