6

Let's assume I want to write a benchmark for the class which can be autowired thus I need to load application context.

My test has annotation @org.openjdk.jmh.annotations.State(Scope.Benchmark) and main method

public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(MyBenchmark.class.getSimpleName())
                .forks(1)
                .build();

        new Runner(opt).run();
    }

And of course I have some benchmarks like this:

@Benchmark
public void countAllObjects() {
    Assert.assertEquals(OBJECT_COUNT, myAutowiredService.count());
}

Now, the question is how do I inject myAutowiredService?

Possible solution

Load manually the context in @Setup method.

ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/application-context.xml");
context.getAutowireCapableBeanFactory().autowireBean(this);

But I don't like this solution. I would prefer that my test just have annotation

@ContextConfiguration(locations = { "classpath:META-INF/application-context.xml" })

and then I just inject my bean like

@Autowired
private MyAutowiredService myAutowiredService;

but this does not work. The reason, I assume, is that I have no annotation that my test should run with Spring:

@RunWith(SpringJUnit4ClassRunner.class)

However there is no point of doing this because I also don't have any @Test annotated methods, thus I will get No runnable methods exception.

Can I achieve loading the context via annotations in this case?

Rufi
  • 2,529
  • 1
  • 20
  • 41

3 Answers3

2

I find the code from spring-cloud-sleuth,it works for me

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
public class DemoApplicationTests {

    volatile DemoApplication app;

    volatile ConfigurableApplicationContext context;

    private VideoService videoService;

    @Test
    public void contextLoads() throws RunnerException {
        Options opt = new OptionsBuilder()
            .include(DemoApplicationTests.class.getSimpleName())
            .forks(1)
            .build();
        new Runner(opt).run();
    }

    @Setup
    public void setup() {
        this.context = new SpringApplication(DemoApplication.class).run();
        Object o = this.context.getBean(VideoService.class);
        videoService = (VideoService)o;
    }

    @TearDown
    public void tearDown(){
        this.context.close();
    }

    @Benchmark
    public String benchmark(){
        return videoService.find("z");
    }
CTD
  • 306
  • 3
  • 8
1
@State(Scope.Benchmark)
public static class SpringState {

    AnnotationConfigApplicationContext context;

    @Setup(Level.Trial)
    public void setup() {
        context = new AnnotationConfigApplicationContext();
        context.register(CLASSNAME.class);
        context.register(ANOTHER_CLASSNAME_TO_BE_LOADED.class);
        context.refresh();
    }

    @TearDown(Level.Trial)
    public void tearDown() {
        context.close();
    }
}
Kanagavelu Sugumar
  • 18,766
  • 20
  • 94
  • 101
0

I would opt for the getAutowireCapableBeanFactory().autowire() solution you already sketched out.

There has to be some boilerplate code that loads the application context and triggers autowiring. If you prefer to specify your app config with annotations the setup method could look something like this:

AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(MyBenchmarkWithConfig.class);
context.refresh();
Fritz Duchardt
  • 11,026
  • 4
  • 41
  • 60
  • For now I still have xml based config, but I guess that one day I will move to annotation based version. So, based on your answer it seems that it is impossible to do it via annotations, is that correct? – Rufi Oct 11 '16 at 09:44
  • I have not tested this, but the AnnotationConfigWebApplicationContext approach should work if you annotate your MyBenchmark class with a @ContextConfiguration that points to an xml file. – Fritz Duchardt Oct 11 '16 at 09:58