mardi 29 décembre 2015

Use Guice to create components to use with ThreadWeaver

The application I have been working on has been getting more and more complicated, and it's gotten to the point where I have been running into the same problems over and over again with concurrency. It no longer made any sense to solve the same problems and not have any regression tests.

That's when I found ThreadWeaver. It was really nice for some simple concurrency cases I cooked up, but I started to get frustrated when trying to do some more complicated cases with my production code. Specifically, when injecting components using Guice.

I've had a bit of a hard time understanding the implications of the way ThreadWeaver runs tests, and looked for any mention of Guice or DI in the wiki documents, but with no luck.

Is Guice compatible with ThreadWeaver?

Here is my test

@Test
public void concurrency_test() {
    AnnotatedTestRunner runner = new AnnotatedTestRunner();
    runner.runTests(OPYLWeaverImpl.class, OPYLSurrogateTranscodingService.class);
}

Here is my test implementation

public class OPYLWeaverImpl extends WeaverFixtureBase {

@Inject private TaskExecutor                 taskExecutor;
@Inject private Serializer                   serializer;
@Inject private CountingObjectFileMarshaller liveFileMarshaller;
@Inject private GraphModel                   graphModel;
@Inject private CountingModelUpdaterService  updaterService;
@Inject private BabelCompiler                babelCompiler;
@Inject private EventBus                     eventBus;

OPYLSurrogateTranscodingService service;

private Path testPath;

@ThreadedBefore
public void before() {
    service = new OPYLSurrogateTranscodingService(eventBus, taskExecutor, serializer, liveFileMarshaller,
            () -> new OPYLSurrogateTranscodingService.Importer(graphModel, babelCompiler, updaterService, eventBus),
            () -> new OPYLSurrogateTranscodingService.Validator(eventBus, babelCompiler),
            () -> new OPYLSurrogateTranscodingService.Exporter(graphModel, updaterService));
}

@ThreadedMain
public void mainThread() {
    testPath = FilePathOf.OASIS.resolve("Samples/fake-powershell-unit-test.opyl");
    service.applyToExistingGraphModel(testPath);
}

@ThreadedSecondary
public void secondaryThread() {

}

@ThreadedAfter
public void after() {

}

And the WeaverFixtureBase

public class WeaverFixtureBase {
@Inject protected CountingEventBus eventBus;

@Before public final void setupComponents() {
    Injector injector = Guice.createInjector(new WeaverTestingEnvironmentModule(CommonSerializationBootstrapper.class));
    injector.getMembersInjector((Class) this.getClass()).injectMembers(this);
}
private class WeaverTestingEnvironmentModule extends AbstractModule {

    private final Class<? extends SerializationBootstrapper> serializationBootstrapper;

    public WeaverTestingEnvironmentModule(Class<? extends SerializationBootstrapper> serializationConfiguration) {
        serializationBootstrapper = serializationConfiguration;
    }

    @Override protected void configure() {
        bind(TaskExecutor.class).to(FakeSerialTaskExecutor.class);
        bind(SerializationBootstrapper.class).to(serializationBootstrapper);
        bind(ModelUpdaterService.class).toInstance(new CountingModelUpdaterService());
        bindFactory(StaticSerializationConfiguration.Factory.class);

        CountingEventBus localEventBus = new CountingEventBus();

        bind(Key.get(EventBus.class, Bindings.GlobalEventBus.class)).toInstance(localEventBus);
        bind(Key.get(EventBus.class, Bindings.LocalEventBus.class)).toInstance(localEventBus);
        bind(CountingEventBus.class).toInstance(localEventBus);
        bind(EventBus.class).toInstance(localEventBus);

    }
    @Provides
    @Singleton
    public GraphModel getGraphModel(EventBus eventBus, Serializer serializer) {
        return MockitoUtilities.createMockAsInterceptorTo(new GraphModel(eventBus, serializer));
    }
}

But when the classloader loads OPYLWeaverImpl, none of the Guice stuff goes off and I get a big pile of nulls.

I feel like this is one of those "missing-something-really-simple" kind of scenarios. Sorry if it is!

Aucun commentaire:

Enregistrer un commentaire