I have the following classes:
public interface Emailer {}
#Named
public class RealEmailer implements Emailer {}
#Named
public class NoOpEmailer implements Emailer {}
And my service class uses the real emailer:
public class SomeService {
#Inject
private Emailer emailer;
}
The question is, in my service test class (SomeServiceTest), how do I inject the Emailer in the service to use NoOpEmailer ? I'm using Spring for the DI framework.
If you can use Spring 3.1 you can use Profiles. This would allow you to provide two different implementations of the same bean (Emailer and NoOpEmailer). Then in your test you can use the #Profile("test") annotation to activate the test profile and your no op bean will be injected.
Have you considered the possibility of making the field package scope rather then private as this would make it a lot simpler to set this field during your unit test (assuming your test class is in the same package as your subject).
If not, it seems to do this with Spring you would use ReflectionTestUtils#setField(Object target, String name, Object value) to inject this value into your class
Related
I have a situation where I want to enable clients to inject their own bean implementing a common interface into my class but otherwise use a default bean.
As an example:
public class TestClass {
// Clients can inject this, otherwise use a default...
#Autowired
private ConfigInjector configInjector;
}
My defined interface and default implementation:
public interface ConfigInjector {
String getConfig();
}
#Component
public class DefaultConfigInjector implements ConfigInjector {
public String getConfig() {
return "DEFAULT CONFIG"
}
}
An external client wants to inject this implementation of my ConfigInjector interface:
#Component
public class ExternalConfigInjector implements ConfigInjector {
public String getConfig() {
return "EXTERNAL CONFIG"
}
}
Using #Autowired in TestClass, if the client attempts to use TestClass with his own ConfigInjector implementation (ExternalConfigInjector), then more than one ConfigInjector implementation will exist, resulting in a NoUniqueBeanDefinitionException exception.
So, how can I share my TestClass with clients allowing them to use their own ConfigInjector to override my default?
you may use #ConditionalOnProperty annotation
according to the name of the variable/argument
using the #primary annotation
using #Qualifier annotation
a recommended free course (1.5 h)
name "Spring Framework And Dependency Injection For Beginners" at www.udemy.com
explains all main issues and use cases.
I've started to use Spring recently. And I'm making spring mvc project. So my question is if it's preferred to make interfaces and autowire it with particular implementation by spring or just use class instances in case when I have only one implementation of that interface?
For example:
#Controller
public class MyController {
#Autowired
MyService myService;
#RequestMap("/")
public String mainPage() {
...
}
}
or
#Controller
public class MyController {
#RequestMap("/")
public String mainPage() {
MyService myService = new MyServiceImpl();
...
}
}
if there is only one implementation of MyService interface?
In most cases you should go with injection because:
It eases unit testing (you can inject mock or different implementation)
Spring can inject some dependencies into MyServiceImpl as well because it manages this object
You are not coupling your controller with particular implementation
Even if your service does not have an interface, because of the second reason you should consider injection.
The only case when you might want to skip Spring is when the class does not have any dependencies and is stateless. But most likely such a class is a utility that does not need any an instance at all because it has only static members.
It will depend on whether MyService is a bean that holds a state or not. If MyService does not hold state, then you don't need to create new instances and you can let Spring to inject it having the advantages above described
I am learning struts+spring, I have a struts action class:
public class Testction{
private String type;
private TestService service;
//...ignore getters and setters here
public String test(){
// action method
}
}
Can Spring inject different TestService implementation according to type parameter ? TestService is just a interface.
If this is possible, where shoud I put #service annotation? on interface or implementation class ?
If that is impossible or hard to go, how to do it in code ?
Spring helps us a lot, but also can make me confused when I want to think deeper.Take above code as example, "type" seems injected by struts, and "service" is injected by spring if TestService is annotated by #service.
so complex...
You can define a #Service annotation on the TestService implementation class.
put #Service annotation on implementation class.you can use #Inject inject TestService into TestAction Class.please remember use javax.inject package.
Hi i am newbie to Spring. While i was writing some sample application using spring annotation using spring annotation i had a query,
Interface Sample{
public void abc();
}
#Service(name = "sample")
Class SampleImpl{
public void abc(){
}
Class MAin{
#Autowired
Sample sam;
My question is can we autowire the implementation class directly,
for example
#Autowired
SampleImpl sampImpl;
if not then why?
Yes, you can, as long as you annotate (or declare in xml) the class you want to autowire.
Spring will find the best match in context by type (and qualifier, if specified).
It's not the best idea though, as it makes testing/mocking more difficult and generally makes components too closely coupled.
I've started to use Spring recently. And I'm making spring mvc project. So my question is if it's preferred to make interfaces and autowire it with particular implementation by spring or just use class instances in case when I have only one implementation of that interface?
For example:
#Controller
public class MyController {
#Autowired
MyService myService;
#RequestMap("/")
public String mainPage() {
...
}
}
or
#Controller
public class MyController {
#RequestMap("/")
public String mainPage() {
MyService myService = new MyServiceImpl();
...
}
}
if there is only one implementation of MyService interface?
In most cases you should go with injection because:
It eases unit testing (you can inject mock or different implementation)
Spring can inject some dependencies into MyServiceImpl as well because it manages this object
You are not coupling your controller with particular implementation
Even if your service does not have an interface, because of the second reason you should consider injection.
The only case when you might want to skip Spring is when the class does not have any dependencies and is stateless. But most likely such a class is a utility that does not need any an instance at all because it has only static members.
It will depend on whether MyService is a bean that holds a state or not. If MyService does not hold state, then you don't need to create new instances and you can let Spring to inject it having the advantages above described