Dependency Injection with PowerMock & Mockito - dependency-injection

How do I create a JUnit testcase for the following class with PowerMock & Mockito.
The class I want to inject is a final class so I'll need to use PowerMock to mock it.
Also note I would prefer to use DI rather than a setter to inject it.
import javax.inject.Inject;
public class ObjectA {
// Use DI to Inject a mock for this 'final' class
#Inject
private ObjectB objectB;
public ObjectA() {
}
public void someMethod() {
if (null == this.objectB) {
throw new IllegalStateException("Failed to inject ObjectB");
}
this.objectB.someOtherMethod();
}
}

No need for PowerMock at this point. Mockito can do all the work.
public class ObjectATest
{
#Mock
private ObjectB objectB;
#InjectMocks
private ObjectA objectA;
#Before
public void setup()
{
MockitoAnnotations.initMocks(this);
}
#Test
public void test()
{
try
{
objectA.someMethod();
}
catch(IllegalStateException e)
{
Assert.fail();
}
}
}

You can use the Whitebox class. For example let's say you've created a mock of ObjectB called objectBMock and an instance of ObjectA called objectA:
Whitebox.setInternalState(objectA, objectBMock);
This will "inject" objectBMock to objectA.

Related

Jersey injection

Is there a way to change the implementation of UriInfo that's injected into all the resources and classes? I want to keep most of the implementation the same, but just change one part of it (the part that provides a UriBuilder - I want to provide a different implementation of the UriBuilder).
You can create wrapper around the original UriInfo
public class MyUriInfo implements UriInfo {
private final UriInfo delegate;
public MyUriInfo(UriInfo uriInfo) {
this.delegate = uriInfo;
}
#Override
public String getPath() {
return delegate.getPath();
}
#Override
public UriBuilder getRequestUriBuilder() {
return new MyUriBuilder();
}
...
}
Then just create a Factory to return your custom UriInfo. This Factory will be used by the DI framework to inject the UriInfo.
public class MyUriInfoFactory
extends AbstractContainerRequestValueFactory<MyUriInfo> {
#Override
public MyUriInfo provide() {
return new MyUriInfo(getContainerRequest().getUriInfo());
}
}
Then just create the AbstractBinder and register it with the ResourceConfig
public class Binder extends AbstractBinder {
#Override
protected void configure() {
bindFactory(MyUriInfoFactory.class)
.to(UriInfo.class)
.in(RequestScoped.class)
.proxy(true)
.proxyForSameScope(false)
.ranked(10);
}
}
public class AppConfig extends ResourceConfig {
public AppConfig() {
register(new Binder());
}
}
If you are using web.xml, check out this post.
Now you should be able to just inject it
#GET
public String get(#Context UriInfo uriInfo) {
return uriInfo.getClass().getName();
}
If you want to be able to retain being able to inject the original UriInfo, you can change the binding to
bindFactory(MyUriInfoFactory.class)
.to(MyUriInfo.class) // <--- Change here to MyUriInfo
.in(RequestScoped.class)
.proxy(true)
.proxyForSameScope(false)
.ranked(10);
This way, you would need to inject MyUriInfo
#GET
public String get(#Context MyUriInfo uriInfo) {
return uriInfo.getClass().getName();
}
Doing this, you are still able to inject the original UriInfo if you needed to.
See Also:
Custom Injection and Lifecycle Management

multiple ejb injections which implement the same interface

i am very new to this ejb stuff. is there any possibility that in a single file i can have multiple injections based on some criteria.
for eg
public interface common(){
public void sayhello();
}
beanA
implements common()
beanB
implements common()
both are stateless beans
now i have a client which needs to trigger hello method based on some criteria. for eg. say based on console input if string contains A then beanA should be injected otherwise beanB.
Is there any possibility? and again my next question is , can i say this dynamic injection is not managed by container? if so how can i let container take the control? i need a sample code or atleast any tutorial ref.
thanks in advance!!
No, this is not really possible. You might be able to get close with a custom CDI scope that uses a thread local or session attribute, but I wouldn't recommend it. Instead, just inject a reference to both EJBs, and select the one to use as needed:
#EJB(beanName="BeanA")
Common beanA;
#EJB(beanName="BeanB")
Common beanB;
private Common getCommon(String input) {
return isBeanAInput(input) ? beanA : beanB;
}
you could do something like this:
public interfaces ICommon {
public void sayhello();
}
#Stateless
#LocalHome
public class BeanA implements ICommon {
public void sayhello() {
// say hallo
}
}
#Stateless
#LocalHome
public class BeanB implements ICommon {
public void sayhello() {
// say hallo
}
}
and here the CDI "client" which uses the EJB services
#Model
public void MyJSFControllerBean {
#Inject
private BeanA beanA;
#Inject
private BeanB beanB;
public String sayhello(final String input) {
if("a".equals(input)) {
beanA.sayhello();
} else {
beanB.sayhello();
}
return "success";
}
}
Or the other solution would be that you create a CDI producer to create this. but then you are mixing two different concepts. but i think it depends ou your concrete usecase.
dynamic injection does not exist! with #Produce and #Qualifier you can control the creation of the required CDI beans to inject. but this is only for CDI not for EJB.
here the CDI producer example:
public void ICommonProducer {
#EJB
private BeanA beanA;
#EJB
private BeanB beanB;
#Produces
public ICommon produce() {
final String input = "?????";
// but here you have the problem that must get the input from elsewhere....
if("a".equals(input)) {
beanA.sayhello();
} else {
beanB.sayhello();
}
}
}
#Model
public void MyJSFControllerBean {
#Inject
private ICommon common;
public String sayhello(final String input) {
common.sayhello();
return "success";
}
}
i have not teseted this code...

Dagger - Is it possible to select a Provider based on inheritance?

At the moment I have a Base class that contains a member I would like to inject. However, I would like the concrete type of this member to depend on the Subclass being instantiated. What I am aiming for is something along these lines:
public interface StringInterface {
public String getString();
}
public class HelloStringConcrete implements StringInterface {
public String getString() {
return "Hello";
}
}
public class WorldStringConcrete implements StringInterface {
public String getString() {
return "World";
}
}
public abstract class Base {
#Inject StringInterface member;
public Base() {
// Assume access to object graph
MyObjectGraph.get().inject(this);
}
public void printSomething() {
System.out.println(member.getString());
}
}
public class SubclassHello extends Base {}
public class SubclassWorld extends Base {}
#Module(injects = {SubclassHello.class})
public class HelloModule {
#Provides StringInterface provideStringInterface() {
return new HelloStringConcrete();
}
}
#Module(injects = {SubclassWorld.class})
public class WorldModule {
#Provides StringInterface provideStringInterface() {
return new WorldStringConcrete();
}
}
So now what I would like to do is something along the lines of:
#Module(
includes = {
HelloModule.class,
WorldModule.class
}
)
public class BigModule {}
// Somewhere in another piece of code...
objectGraph = ObjectGraph.create(new BigModule());
// In yet another piece of code...
SubclassHello hello = new SubclassHello();
SubclassWorld world = new SubclassWorld();
hello.printSomething();
world.printSomething();
// Hopefully would result in :
// Hello
// World
This type of setup won't work though, because including two modules with the same provider will result in a duplicate provider error at compile time. It would be cool to see a solution to this problem without introducing #Named or #Qualifer annotations, or using scoped graph extensions via graph.plus() because these strategies necessarily introduce coupling to the subclasses
This is possible but I think the code I've attached below is more coupled than using scoped graphs or annotations. Basically you can use constructor injection to inject concrete dependencies to your
SubclassHello and SubclassWorld.
public abstract class Base {
private final StringInterface member;
public Base(StringInterface member) {
this.member = member;
}
...
}
#Module(injects = {SubclassWorld.class})
public class WorldModule {
#Provides
WorldStringConcrete provideStringInterface() {
return new WorldStringConcrete();
}
}
public class SubclassWorld extends Base {
#Inject
public SubclassWorld(WorldStringConcrete worldStringConcrete) {
super(worldStringConcrete);
}
}
#Module(injects = {SubclassHello.class})
public class HelloModule {
#Provides
HelloStringConcrete provideStringInterface() {
return new HelloStringConcrete();
}
}
public class SubclassHello extends Base {
#Inject
public SubclassHello(HelloStringConcrete helloStringConcrete) {
super(helloStringConcrete);
}
}
// Somewhere in another piece of code...
ObjectGraph objectGraph = ObjectGraph.create(new BigModule());
// In yet another piece of code...
SubclassHello hello = objectGraph.get(SubclassHello.class);
SubclassWorld world = objectGraph.get(SubclassWorld.class);
I don't think there are other solutions. How could Dagger find out which StringInterface implementations should be injected to the concrete classes?

Jersey #Context scope

I have a hard time understanding the injection mechanism of Jersey. The JAX-RS Specification (http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-520005) states that injection via #Context is possible in Application subclasses, root resource classes and providers.
I now have a class that is instantiated at startup and has a method which is called on every request. Inside the method I need access to the current UriInfo object. The problem is, that this method is not called from my code. So I can't pass UriInfo directly to the method.
I actually want to do something like this:
public class MyClass implements ThirdPartyInterface {
// not possible because class is no Application subclass, root resource class or provider
#Context
private UriInfo uriInfo;
public void methodCallebByThirdPartyCode() {
Uri requestUri = uriInfo.getRequestUri();
// do something
}
}
I tried this. Obviously with no success:
public class MyClass implements ThirdPartyInterface {
private UriInfo uriInfo;
public MyClass(UriInfo uriInfo) {
this.uriInfo = uriInfo;
}
public void methodCallebByThirdPartyCode() {
Uri requestUri = uriInfo.getRequestUri();
// do something
}
}
#Provider
#Produces(MediaType.WILDCARD)
public class MyBodyWriter implements MessageBodyWriter<MyView> {
#Context
private UriInfo uriInfo;
private MyClass myClass;
private ThirdPartyClass thirdPartyClass;
public MyBodyWriter() {
// uriInfo is null at this time :(
myClass = new MyClass(uriInfo);
thirdPartyClass = new ThirdPartyClass();
thirdPartyClass.register(myClass);
}
public void writeTo(final MyView view, final Class<?> type, /* and so on */) throws IOException, WebApplicationException {
// execute() calls MyClass#methodCallebByThirdPartyCode()
thirdPartyClass.execute();
}
}
The only workaround I can think of is this. I don't think it's very clean:
public class MyClass implements ThirdPartyInterface {
private UriInfo uriInfo;
public void setUriInfo(final UriInfo uriInfo) {
this.uriInfo = uriInfo;
}
public void methodCallebByThirdPartyCode() {
Uri requestUri = uriInfo.getRequestUri();
// do something
}
}
#Provider
#Produces(MediaType.WILDCARD)
public class MyBodyWriter implements MessageBodyWriter<MyView> {
#Context
private UriInfo uriInfo;
private MyClass myClass;
private ThirdPartyClass thirdPartyClass;
public MyBodyWriter() {
myClass = new MyClass();
thirdPartyClass = new ThirdPartyClass();
thirdPartyClass.register(myClass);
}
public void writeTo(final MyView view, final Class<?> type, /* and so on */) throws IOException, WebApplicationException {
myClass.setUriInfo(uriInfo);
// execute() calls MyClass#methodCallebByThirdPartyCode()
thirdPartyClass.execute();
myClass.setUriInfo(null);
}
}
I hope there is a better solution, but maybe I'm completely on the wrong track.
Thanks!
Late answer, but a good question ... so lets go:
You can use a org.glassfish.hk2.api.Factory and javax.inject.Provider for injections. I don't know since which version this is available, so maybe you have to upgrade your jersery version. For the following samples i used jersey 2.12.
First you have to implement and register/bind a Factory for your MyClass:
MyClassFactory:
import javax.inject.Inject;
import javax.ws.rs.core.UriInfo;
import org.glassfish.hk2.api.Factory;
// ...
public class MyClassFactory implements Factory<MyClass> {
private final UriInfo uriInfo;
// we will bind MyClassFactory per lookup later, so
// the constructor will be called everytime we need the factory
// meaning, uriInfo is also per lookup
#Inject
public MyClassFactory(final UriInfo uriInfo) {
this.uriInfo = uriInfo;
}
#Override
public MyClass provide() {
return new MyClass(uriInfo)
}
#Override
public void dispose(UriInfo uriInfo) {
// ignore
}
}
Registration via ResourceConfig:
import org.glassfish.hk2.api.PerLookup;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.server.ResourceConfig;
// ...
public class MyResourceConfig extends ResourceConfig {
public MyResourceConfig() {
register(new AbstractBinder() {
#Override
protected void configure() {
bindFactory(MyClassFactory.class).to(MyClass.class).in(PerLookup.class);
// ... bind additional factories here
}
});
// ...
}
}
Now you are able to inject MyClass per lookup to providers, resources etc.
But Attention: Afaig there are two approaches and only one will work as eventually aspected for providers ...
import javax.inject.Inject;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
// ...
#Provider
#Produces("application/foo-bar")
public class MyBodyWriter implements MessageBodyWriter<MyView> {
// first approache - don't do it!
// will only injected once, cause MyBodyWriter is only instantiated once
#Inject
private MyClass myClass;
// second approache - works fine!
private final javax.inject.Provider<MyClass> provider;
// MyBodyWriter instantiate once
// get an inject provider here
#Inject
public MyBodyWriter(javax.inject.Provider<MyClass> myClassProvider) {
this.provider = myClassProvider;
}
#Override
public boolean isWriteable(Class<?> t, Type g, Annotation[] a, MediaType m) {
return t == MyView.class;
}
#Override
public long getSize(MyView t, Class<?> c, Type g, Annotation[] a, MediaType m) {
// deprecated by JAX-RS 2.0 and ignored by Jersey runtime
return 0;
}
#Override
public void writeTo(MyView v, Class<?> c, Type t, Annotation[] a, MediaType m, MultivaluedMap<String, Object> s, OutputStream o) throws IOException, WebApplicationException {
// attention: its not per lookup !!!
MyClass myClassDirectInjected = myClass;
System.out.println(myClassDirectInjected); // same instance everytime
// but this is ;)
MyClass myClassFromProvider = provider.get();
System.out.println(myClassFromProvider); // it's a new instance everytime
// ...
}
}
Hope this was somehow helpfull.

How to inject an instance of a class with a parameterized constructor using CDI (Java EE 6 only)

I'm new to CDI, tried searching for the usage, could not find anything and so posting the question. I'm trying to figure how I can inject an instance of a class with a parameterized constructor only using CDI. I'm not using Spring so, how it is done in spring does not help. Here is a sample I've created to show what's the issue. My #Inject will not work in this scenario.
public class A
{
public A(boolean deliverFromLocalWarehouse)
{
if(deliverFromLocalWarehouse)
{
wareHouseId = new Integer(10);
}
else
{
wareHouseId = new Integer(100);
}
}
public void deliver()
{
//get wareHouse address by Id and initiate delivery.
}
private Integer wareHouseId = null;
}
public class B
{
#Inject
private A a;
}
Thanks
Srikrishna Kalavacharla
If the constructor parameter should come from a bean, I think you can simply annotate it:
public A(#Inject boolean localWarehouse) { ...
and inject it with
#Inject A a;
If you want two different instances of A (with different constructor arguments), you could subclass them:
public AForLocalWarehouse extends A {
public AForLocalWarehouse() {
super(true);
}
}
and inject them with
#Inject AForLocalWarehouse a;
or use a producer method with qualifiers:
#Produces #LocalWarehouse
public A localWarehouse() { return new A(true); }
#Produces #RemoteWarehouse
public A remoteWarehouse() { return new A(false); }
and inject them with
#Inject #LocalWarehouse A a;
#Inject #RemoteWarehouse A a;

Resources