I am working on a Java EE 7 (on wildfly 9.0.2) application and I stumbled on an article http://www.oracle.com/technetwork/articles/java/intondemand-1444614.html. Mainly about:
Premature Extensibility Is the Root of Some Evil
This makes sense in certain cases I have encountered. I have changed some classes to a no interface view. The implementation itself is not a problem, testing however is.
For example I have these 2 classes.
#Stateless
public class SomeBean {
public String getText()
{
return "Test text";
}
}
And
#Stateless
public class SomeOtherBean {
#Inject
private SomeBean someBean;
public String getText()
{
return someBean.getText();
}
}
I want somehow that the someBean property is overwritten with preferably a mocked object. Without altering the SomeBean and SomeOtherBean class. I have tried some examples, but they didn't work for example:
https://github.com/arquillian/arquillian-showcase/tree/master/extensions/autodiscover/src/test/java/org/jboss/arquillian/showcase/extension/autodiscover
Has anyone encountered this before and have a solution?
I ended up using 2 solutions.
Solution 1: Use mockito for internal or smaller tests
For testing a particular class Mockito is really useful, as it supports dependency injection.
#RunWith(MockitoJUnitRunner.class)
public class SomeOtherBeanTest {
#Mock
private SomeBean someBean;
#InjectMocks
private SomeOtherBean someOhterBean;
#Before
public void setUp() {
Mockito.when(someBean.getText()).thenReturn("Overwritten!");
}
#Test
public void testGetText() throws Exception {
assertEquals("Overwritten!", someOhterBean.getText());
}
}
Solution 2: Use #Produces and #Alternatives for mocking external services (e.g. mocking OAuth2 server) or larger test (e.g. integration testing)
First I create a new #Alternative annotation:
#Alternative
#Stereotype
#Retention(RUNTIME)
#Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
public #interface CDIMock {}
Then add this as stereotype to the arquillian beans.xml deployment:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="all">
<alternatives>
<stereotype>com.project.CDIMock</stereotype>
</alternatives>
</beans>
After that create a new #Producer method in a seperate class:
public class SomeBeanMockProducer {
#Produces #CDIMock
public static SomeBean produce() {
SomeBean someBean = Mockito.mock(SomeBean.class);
Mockito.when(someBean.getText()).thenReturn("mocked");
return someBean;
}
}
Add the SomeBeanMockProducer class to the arquillian deployment and you should have it working.
An alternative to this solution is using #Specializes and extending the SomeBean implementation. In my opinion this doesn't give me enough control like the #Alternative + Mocking solution (#CDIMock in my example).
For example, lets say I SomeBean has methods that calls remote servers. If I add a method to this and forget to #override this in the #Specializes class it will make a real remote call, this won't be the case with Mocking.
It is kind of obvious that substituting a Mock or other specialized object for an injected no-interface class is more difficult, since that is exactly what you wanted by not declaring an interface for the bean.
Having said that, if you are not running a CDI container (e.g. doing POJO unit tests) I think using Mockito is the easiest way.
If you want to do it the "pure CDI" way within a container, you can use the Alternative and Specialization mechanisms of CDI, as described in the Java EE 6 tutorial.
#Specializes
public class SomeBeanMock extends SomeBean {
#Overrides
public String getText()
{
return "mock";
}
}
Of course you can only use mocks that subclass the original bean (since you have no interface) and you are limited to the usual visibility rules. Changing/mocking private field or methods would require reflection or bytecode manipulation (which is what Mockito does behind the scenes).
Related
In a real project, I found out that #Component may be omitted in the following code:
// no #Component !!!!!
public class MovieRecommender {
private final CustomerPreference customerPreference;
#Autowired
public MovieRecommender(CustomerPreference customerPreference) {
this.customerPreference = customerPreference;
}
// ...
}
#Component
public class CustomerPreference {...}
(The example is taken from the official Spring docs https://docs.spring.io/spring-framework/docs/4.3.x/spring-framework-reference/htmlsingle/#beans-autowired-annotation , and the docs show no #Component at all, which may mean either that it is not needed, or that it is just not shown.)
The project where I work does not use any XML bean declarations, but it uses frameworks other than just Spring, so it is possible that something declares the class as a bean. Or it may be a feature of the version of Spring that we use, and if that feature is not documented, it may be dropped later.
Question:
Must the class that uses #Autowired be annotated with #Component (well, be a bean)? Is there any official documentation about that?
UPD Folks, there is no #Configuration and no XML configs in the project, I know that such declarations make a bean from a class, but the question is not about them. I even wrote "(well, be a bean)" in the question above to cover that. Does #Autowired work in a class that is not a bean? Or maybe it declares the class that uses it as a bean?
there are several ways to instantiate a bean in Spring.
One of them indeed is with the #Component annotations, with that, Spring will scan all the packages defined for component-scan and initialize all annotated classes (either with #Component or one of the annotations that uses it - Controller, Service, etc.).
Other way to initialise beans is using a configuration class (annotated with #Configuration) that includes methods annotated with #Bean. each of these methods will create a bean.
There's also an option to create the beans using xml configurations, but this is becoming less and less common, as the annotation-based approach is more convinient
According to https://stackoverflow.com/a/3813725/755804 , with autowireBean() it is possible to autowire a bean from a class not declared as a bean.
#Autowired
private AutowireCapableBeanFactory beanFactory;
public void sayHello(){
System.out.println("Hello World");
Bar bar = new Bar();
beanFactory.autowireBean(bar);
bar.sayHello();
}
and
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
public class Bar {
#Autowired
private Foo foo;
public void sayHello(){
System.out.println("Bar: Hello World! foo="+foo);
}
}
On the other hand, by default the latest Spring does not assume that classes that use #Autowire are #Component-s.
UPD
As to the mentioned real project, the stack trace shows that the constructor is called from createBean(). That is, the framework creates beans from classes declared in the framework's configs.
I have a question that I can't answer myself - at least not well.
Imagine following code:
#Service
public class ServiceA {
public void doService() {
System.out.println("Doing ServiceA");
}
}
#Service
public class ServiceB {
#Autowired
ServiceA serviceA;
public void doService() {
serviceA.doService();
}
}
It works, but is it considered bad practice? If you want to decouple these classes or test them, you have no way to ever manually set the dependencies.
Also, how exactly is Spring handling it? Is there created a proxy class with an added constructor for the property?
If it is a bad practice or not depends for the era in which you write this code. In the era of EJB it is a best practice, the container provide you all the feature of the lifecycle and even in Spring it is good even if some time even in Spring this is quite rigid model java config or xml is a more flexible solution.
However in the 20xx era especially in a TDD and Agile model, I can say that it is a real BAD PRACTICE. Those beans are not testable out of the Spring container and the annotation couple you at Spring even in compile time. a more best solution may be a code like below
class ServiceA {
public void doService() {
System.out.println("Doing ServiceA");
}
}
class ServiceB {
private final ServiceA serviceA;
ServiceB(ServiceA serviceA) {
this.serviceA = serviceA;
}
public void doService() {
serviceA.doService();
}
}
#Configuration
class ServiceConfig{
#Bean
public ServiceA serviceA(){
return new ServiceA();
}
#Bean
public ServiceB serviceB(ServiceA serviceA){
return new ServiceB(serviceA);
}
}
In this way ServiceA and ServiceB classes are two totally Spring free bean and especially for the business logic it is a best practice, the bean are testable because the our dependencies are explicit.
Imagine of provide a test of the ServiceB class writing the code in this way you can stub or mock the serviceA dependency and the ServiceB bean can be tested in isolation.
For the proxy story do not worry about it since that we provide a configuration class ServiceA and ServiceB are two beans like the annotated class, Spring manage a java config bean like an annotated bean. The difference is that now we can benefit of an explicit composition and we can provide a more flexible configuration scenario. we can benefit again of the magic aop of Spring because like said before an Spring bean configured in Java config is totally equivalent respect to an annotated bean.
I suggest you to use java config like the example.
I hope that it can help you
update:
to reply to:
Also, how exactly is Spring handling it? Is there created a proxy class with an added constructor for the property?
I can say: with the component-scan feature let's say #ComponentScan, spring find all the bean that are annotated with a sterotype annotation like #Component, #Service, #Repository and so on some of this annotation are useful because trigger some feature, for example #Repository if we implement a JPA repository and register a PersistanceExceptionTraslatorPostProcessor that translate the SQL native exception in an Exception of DataAccessException hierarchy, but other annotation are just a way for register a spring bean with annotation #Component, #Service are example.
Spring by relfection create the bean and inject the field annotated with #Autowired, if you use #Autowired on field by reflection set directly the field otherwise use the setter, in xml for instance the setter or the constructor are required.
In case of two constructor for you it is transparent, Spring will use the empty constructor and then will provide the #Autowired property by reflection, you can even do like below:
#Service
class ServiceA {
public void doService() {
System.out.println("Doing ServiceA");
}
}
#Service
class ServiceB {
private ServiceA serviceA;
public ServiceB() {
}
#Autowired
public ServiceB(ServiceA serviceA) {
this.serviceA = serviceA;
}
public void doService() {
serviceA.doService();
}
}
In this case spring recognize that it have use the annotated constructor with #Autowired in order to create the bean and provide the dependency. In any case the best practice is definitely the first snippet of code in my answer. It is explicit in the dependencies, clean and Spring Free in your business code base
If you dont like autowired (me either). You can used Constructor Dependency Injection.
You should not used depencendy for class byt for interface and spring will server correct implementation (decoupling)
public interface ServiceA {
public void doService();
}
#Service
public class ServiceAImpl implement ServiceA {
public void doService() {
System.out.println("Doing ServiceA");
}
}
#Service
public class ServiceBImpl implements ServiceB {
private final ServiceA serviceA;
public ServiceBImpl(ServiceA serviceA) {
this.serviceA = serviceA;
}
public void doService() {
serviceA.doService();
}
}
I'm trying to replace an #Autowired object with a Mockito mock object. The usual way of doing this was with xml using Springockito:
<mockito:mock id="SomeMock" class="com.package.MockInterface" />
Currently I'm trying to move over to using Spring's JavaConfig to do the job. All of a sudden the Java expressions are a whole lot more verbose than xml:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class MyTestClass {
#Configuration
static class Config {
#Bean
public MockInterface somethingSpecial() {
return Mockito.mock(MockInterface.class);
}
}
#Autowired MockInterface mockObj;
// test code
}
I discovered a library called Springockito-annotations, which allows you to do the following:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader=SpringockitoContextLoader.class)
public class MyTestClass {
#Autowired #ReplaceWithMock MockInterface mockObj;
// test code
}
Clearly, a whole lot prettier :) The only problem is that this context loader doesn't allow me to use #Configuration and JavaConfig for other beans (if I do, Spring complains that there are no candidates that match those autowired fields).
Do you guys know of a way to get Spring's JavaConfig and Springockito-annotations to play nice? Alternatively, is there another shorthand for creating mocks?
As a nice bonus, using Springockito and xml config, I was able to mock out concrete classes without providing autowiring candidates to its dependencies (if it had any). Is this not possible without xml?
Moving away from the now unmaintained (as of this writing) Spingockito-annotations and to Mockito, we have a way of doing this very simply:
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration
public class MyTestClass {
#Mock MockInterface mockObj;
// test code
}
If you're using a real object, but would like to mock a dependency within it, for instance testing a service layer with DAO:
#RunWith(MockitoJUnitRunner.class)
#ContextConfiguration
public class MyTestClass {
#InjectMocks RealService;
#Mock MockDAO mockDAO;
// test code
}
Finally, this can also be applied to Spring-boot, but using annotation initialization within setUp() until multiple class runners are supported:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyMainSpringBootClass.class)
public class MyTestClass {
#InjectMocks RealService;
#Mock MockDAO mockDAO;
#Before
public final void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
}
// test code
}
Outdated and deprecated!
Read about mocking and spying in Spring Boot 1.4
Please read also #ethesx answer,
Springockito is unmaintaned
Old answer
This is possible now to mock Spring application without any XML file with Springockito-annotations.. This solution works also with Spring Boot.
import static org.mockito.BDDMockito.*;
import org.kubek2k.springockito.annotations.*;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = Application.class,
loader = SpringockitoAnnotatedContextLoader.class)
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class MainControllerTest {
#Autowired
MainController mainController;
#Autowired
#ReplaceWithMock
FooService fooService;
#Test
public void shouldGetBar() {
//given
given(fooService.result("foo")).willReturn("bar");
//when
Bar bar build = fooService.getBar("foo");
//then
assertThat(bar).isNotNull();
}
}
Dependencies: org.kubek2k:springockito-annotations:1.0.9
It appears that SpringockitoContextLoader extends GenericXmlContextLoader which is described as:
Concrete implementation of AbstractGenericContextLoader that reads bean definitions from XML resources.
So you are limited to xml bean definitions at the moment.
You could write your own context loader, taking relevant parts from the SpringockitoContextLoader class. Take a look here to get started, perhaps you could extend AnnotationConfigContextLoader for example?
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 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