Hey Guys,
I've an issue on testing my resource. The issue is about injecting and mocking variable in my resource code. As examples helping most to explain issues, see consecutively.
Pretend I've (minimal) Resource like this one:
```java
@Path("/myURL")
@Produces(MediaType.APPLICATION_JSON)
public class ExportResource {
// ----------------------------------------------
// CONSTANTS
// ----------------------------------------------
/** Resource-Logger. */
protected static final Logger LOGGER = LoggerFactory
.getLogger(AbstractExportResource.class);
// ----------------------------------------------
// Class Variables
// ----------------------------------------------
@Inject
protected Subject subject;
// methods not given, as they are not necessary here
}
```
Injection works fine, as I'm using this (minimal) Application code:
```java
public class ExportApplication extends
Application<ExportConfiguration> {
public static void main(String[] args) throws Exception {
new ExportApplication().run(args);
}
@Override
public String getName() {
return "Export";
}
@Override
public void initialize(Bootstrap<ExportServiceConfiguration> bootstrap) {
// nothing to do yet
}
@Override
public void run(ExportServiceConfiguration configuration,
Environment environment) {
final Client httpClient = new JerseyClientBuilder(environment).using(
configuration.getJerseyClientConfiguration()).build(getName());
// register Subject as SubjectFactory
environment.jersey().register(new AbstractBinder() {
@Override
protected void configure() {
bindFactory(SubjectFactory.class).to(Subject.class).in(RequestScoped.class).proxy(true);
}
});
// register resource
environment.jersey().register(
new ExportResource(httpClient, configuration));
}// run
}// ExportApplication
```
Just to provide full code, see (minimal) SubjectFactory:
```java
public class SubjectFactory implements Factory<Subject> {
@Inject
private HttpServletRequest request;
@Override
public Subject provide() {
Subject s = new Subject();
s.setName("Paul");
return s;
}
@Override
public void dispose(Subject instance) {
}
}
```
and (minimal) Subject:
```java
public class Subject {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
```
If I want to test the resource, I'm using ResourceTestRule:
```java
RunWith(MockitoJUnitRunner.class)
public class ExportTest {
protected static final ExportConfiguration configuration = new ExportConfiguration();
@Mock (name="subject")
protected static final Subject subject = mock(Subject.class);
// ----------------------------------------------------
// JUNIT specific variables
// ----------------------------------------------------
@InjectMocks
private static ExportResource exportResource = new ExportResource();
@ClassRule
public static final ResourceTestRule resources = ResourceTestRule.builder()
.addResource(exportResource).build();
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
reset(subject);
}// setup
@AfterClass
public static void tearDownClass() {
// nothing to do atm
}
@Test
public void testSuccessTestConnection() {
Response response = resources.client().target("/myURL/test")
.request().get(Response.class);
/** Check: Response.getCode = 200 */
Assert.assertEquals("Different status code expected", 200,
response.getStatus());
}// testSuccessTestConnection
}
```
Doesn't work, as I get faced with this error:
```
MultiException stack 1 of 1
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=Subject,parent=AbstractExportResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,1921028872)
at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)
at org.jvnet.hk2.internal.Utilities.justInject(Utilities.java:945)
at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:923)
at org.jvnet.hk2.internal.ServiceLocatorImpl.inject(ServiceLocatorImpl.java:913)
at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:575)
at org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:166)
at org.glassfish.jersey.server.ApplicationHandler$3.run(ApplicationHandler.java:327)
at org.glassfish.jersey.internal.Errors$2.call(Errors.java:289)
at org.glassfish.jersey.internal.Errors$2.call(Errors.java:286)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.processWithException(Errors.java:286)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:324)
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:277)
at org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory$InMemoryTestContainer.<init>(InMemoryTestContainerFactory.java:77)
at org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory$InMemoryTestContainer.<init>(InMemoryTestContainerFactory.java:63)
at org.glassfish.jersey.test.inmemory.InMemoryTestContainerFactory.create(InMemoryTestContainerFactory.java:111)
at org.glassfish.jersey.test.JerseyTest.createTestContainer(JerseyTest.java:277)
at org.glassfish.jersey.test.JerseyTest.setUp(JerseyTest.java:609)
at io.dropwizard.testing.junit.ResourceTestRule$1.evaluate(ResourceTestRule.java:198)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
```
Obviously, the injection is not working. After googling for a while and doing research on this topic it has turned out, injectMocks doesn't wok on static variables. And as we see above, the ResourceTestRule is static and the Rule needs to be static. Therefore, the ExportResource needs to be static as well which is causing the problem.
Do you guys know to deal with that?
Thanks in advance.
All the best!