/*
* Copyright 2012 Harald Wellmann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.ops4j.pax.exam.junit;
import java.lang.reflect.Method;
import org.junit.rules.ExternalResource;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.ExamSystem;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.TestContainer;
import org.ops4j.pax.exam.spi.DefaultExamSystem;
import org.ops4j.pax.exam.spi.PaxExamRuntime;
/**
* JUnit rule for launching a Pax Exam container in server mode for a JUnit test.
* <p>
* Example
*
* <pre>
*
*
* public class MyTest {
*
* @Rule
* public PaxExamServer exam = new PaxExamServer();
* }
* </pre>
*
* This rule starts a Pax Exam container before each test and stops it after the test. The
* configuration options for the exam container are taken from a method in the test class annotated
* with {@link Configuration}. The test class must contain a unique no-args method with this
* annotation and with return type {@code Option[]}.
* <p>
* Alternatively, you can pass a class literal to the {@code PaxExamServer} constructor. In this
* case, the {@code @Configuration} method will be taken from the class argument.
* <p>
* This test rule can be used with any plain old unit test or in combination with other JUnit
* runners. Do not use this rule in combination with the {@link PaxExam} runner.
* <p>
* {@code PaxExamServer} can also be used as a class rule. In this case, test container is started
* once before running all tests of the class and is stopped when all tests have run.
*
* @author Harald Wellmann
*/
public class PaxExamServer extends ExternalResource {
private Class<?> configClass;
private TestContainer testContainer;
public PaxExamServer() {
}
public PaxExamServer(Class<?> configClass) {
this.configClass = configClass;
}
@Override
public Statement apply(Statement base, Description description) {
if (configClass == null) {
configClass = description.getTestClass();
}
return super.apply(base, description);
}
@Override
protected void before() throws Exception {
Option[] options = getConfigurationOptions();
ExamSystem system = DefaultExamSystem.create(options);
testContainer = PaxExamRuntime.createContainer(system);
testContainer.start();
}
@Override
protected void after() {
testContainer.stop();
}
private Option[] getConfigurationOptions() throws Exception {
Method m = getConfigurationMethod(configClass);
Object configClassInstance = configClass.newInstance();
Option[] options = (Option[]) m.invoke(configClassInstance);
return options;
}
private Method getConfigurationMethod(Class<?> klass) {
Method[] methods = klass.getMethods();
for (Method m : methods) {
Configuration conf = m.getAnnotation(Configuration.class);
if (conf != null) {
return m;
}
}
throw new IllegalArgumentException(klass.getName() + " has no @Configuration method");
}
}