In my quarkus app, I have repository implementations in a separate gradle project/module, partly because I want to be able to ensure unit tests don't use the database etc.
The trouble is, if I want to use any injected dependencies in test, I need to use #QuarkusTest, and then the build or startup ensures that all dependencies are satisfied.
Is there any way around this that doesn't involve mocking every single external dependency, e.g.?
Don't enforce dependencies during build or startup when running tests, and instead leave it to error during runtime if accessed.
Some way of mocking all unavailable dependencies (or a subset of them) with a mock that errors on access.
I am using weld-junit to run unit tests on CDI components. In the past I have been using cdiunit too which is great, but it does not support JUnit 5. The idea of both is to launch the tests inside a real CDI container, in a minimal configuration. The important part is that you control explicitly what beans are available for injection, so the system skips the bean discovery part. This makes the tests fairly fast: the CDI overhead is only a few seconds. Both systems allow you to provide mock instances for any dependencies you want - I have been using Mockito for managing the mocks.
The minimal Maven setup (see here is to use a version of the Maven surefire plugin that enables JUnit 5, e.g.:
<pluginManagement>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<plugin>
</pluginManagement>
And the other dependencies:
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-junit5</artifactId>
<version>${version.weld-junit5}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${version.junit.jupiter}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${version.junit.jupiter}</version>
<scope>test</scope>
</dependency>
<!-- If you want Mockito: -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${version.mockito}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${version.mockito}</version>
<scope>test</scope>
</dependency>
Having these in place, you can write & run a test (an example) for your CDI beans (example):
// weld-junit5 annotation - there are other ways to activate weld-junit5
// in your tests, and more features for controlling the container,
// read the full docs!
#EnableAutoWeld
// add real bean implementations in the DI container
#AddBeanClasses(RealBeanDependency.class)
// add extensions if you need
#AddExtensions({Extension1.class, Extension2.class})
// activate scopes, if you need
#ActivateScopes(RequestScoped.class)
// add automatic creation of mocks with Mockito (#Mock)
#ExtendWith(MockitoExtension.class)
public class MyClassTest {
// an example of introducing mocks to the DI container
#Produces #Mock
private ArticleService articleService;
// injected the "System Under Test"
// weld-junit will automatically add it to the available beans
#Inject
private MyClass sut;
#Test
void test() {
// this runs inside the minimal CDI container
// read the docs about details, e.g. it starts
// a fresh container for each test (I think)
}
}
Related
I am trying to test a Camel Blueprint route. I am using camel version 2.12 and camel-jsonpath is available as of version 2.13. So instead of camel-jsonpath, I am trying to use
json-path itself in my unit tests. But as soon as adding the json-path dependency, my unit tests are failing.
This is the dependency ;
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.2.0</version>
<scope>test</scope>
</dependency>
My test class extends from CamelBlueprintTestSupport and after adding this dependency I got the following exception;
java.lang.RuntimeException: Gave up waiting for service (objectClass=org.apache.camel.CamelContext)
In the Jetty 9.3.1 documentation the Class HttpTester is referenced, however it doesn't appear to be in any of the jar files provided in the download package.
HttpTester.Request request = HttpTester.newRequest();
request.setURI("/some/resource");
HttpTester.Response response =
HttpTester.parseResponse(HttpTester.from(localConnector.getResponse(request.generate())));
I want to use HttpTester.Response and HttpTester.Request in my unit test cases.
Was this class removed in 9.3.1? If so, is there a recommended alternative?
It was moved to the tests classified artifacts.
Try this (in maven-speak):
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<version>9.3.11.v20160721</version>
<classifier>tests</classifier>
</dependency>
I was working on SOAP JAX-WS with CQ5. I was trying the example available on link "_http://cqblog.inside-solutions.ch/2013/11/01/consuming-soap-web-service-with-jax-ws-in-cq5-6-1/". I used the command "wsimport -keep -verbose http://www.w3schools.com/webservices/tempconvert.asmx?wsdl" to generate the stubs. When i am calling this below line in my WebServiceClient class, i am getting error as "A WebService annotation is not present on class: com.mercer.jaxws.TempConvertSoap". TempConvertSoap is a proxy class.
*line :-
return super.getPort(new QName("_http://www.w3schools.com/webservices/", "TempConvertSoap"), TempConvertSoap.class);
i am adding the below dependencies to resolve the required jars in maven pom.xml :-
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-ws-metadata_2.0_spec</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>javax.xml.ws</groupId>
<artifactId>jaxws-api</artifactId>
<version>2.2.8</version>
</dependency>
Please provide pointers on the same.
Thanks,
Kiran Parab
Trying to set up a JPA+EJB testing after these instructions:
http://ctpjava.blogspot.fi/2009/10/unit-testing-ejbs-and-jpa-with.html
There seems to be few problems that I can't seem to get quite right.
First I get this error (which I am able to work around, but it still needs to be fixed):
SEVERE: EJB6004:Specified application server installation location [C:\Users\<userName>\.m2\repository\org\glassfish\extras\glassfish-embedded-all\domains\domain1] does not exist.
Found this site, which gives the (more correct?) properties to set:
http://docs.oracle.com/cd/E18930_01/html/821-2424/gjlde.html
And modified my testing setup to this:
import javax.ejb.embeddable.EJBContainer;
import javax.naming.Context;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
...
#BeforeClass
public static void createContainer() {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(EJBContainer.MODULES, new File("target/classes"));
properties.put("installation.root", "./src/test/glassfish");
properties.put("configuration.file", "./src/test/glassfish/domains/domain1/config/domain.xml");
container = EJBContainer.createEJBContainer(properties);
ctx = container.getContext();
}
And in pom.xml I have the following that seems to be required for this:
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.9.1.0</version>
<scope>test</scope>
</dependency>
<!-- Must be before java-ee -->
<dependency>
<groupId>org.glassfish.extras</groupId>
<artifactId>glassfish-embedded-all</artifactId>
<version>3.1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
The error pointed into user directory and I was able to get pass this by setting up the required stuff there (and got past this), but that is not a proper place, since everything must be available via SVN.
According to the latter link I think I have the correct properties set, but those seem to be ignored. Maybe I am missing something obvious?
Missed this text in the properties link:
Properties that can be passed to the
EJBContainer#createEJBContainer(Properties) method are summarized in
the following table. All properties are in the
org.glassfish.ejb.embedded.glassfish package. For example, the full
name of the installation.root property is
org.glassfish.ejb.embedded.glassfish.installation.root.
So the answer was to have:
org.glassfish.ejb.embedded.glassfish.
Before each property
Thus:
org.glassfish.ejb.embedded.glassfish.installation.root
intead of:
installation.root
I compile my programm against javaee-api. But for Junit testing I must use a specific implementation like glassfish's javaee.jar to avoid errors like java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/persistence/Persistence (see also 1).
So avoid using methods, that are only available in glassfish implementation, I want to compile my artifact with the general api, but run junit with the implementation jar. But both provide equal named classes and inferfaces, so the class loader gets in trouble.
What is the best way to solve this problem? Can I solve this problem with maven?
Thanks a lot
I think that this is possible. Actually, starting with version 2.0.9, Maven uses the POM order to build the classpath, so you can manipulate it now. And if you combine this with Dependency Scope, it should be possible to achieve what you want. In practical terms, if you place GlassFish's javaee dependency (with a test scope) before the javaee-api dependency, the former should be placed before the later in the test classpath and thus used by unit tests while the later will be used during compile. In theory, this should work but it is kinda fragile so it needs to be carefully documented.
Something like that (with a fictional GFv3 jar):
<dependencies>
<dependency><!-- this one will be first on the test classpath -->
<groupId>org.glassfish</groupId>
<artifactId>javaee</artifactId>
<version>6.0</version>
<scope>test</scope>
<dependency>
<dependency><!-- this one will be used during compile -->
<groupId>javax.javaee-api</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
<dependency>
...
</dependencies>