Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override the behavior of Spring @Autowired

A little background:

I am Using Spring 2.5, and specifically Spring IOC and annotations.

I am using @Autowired in my code (the Autowiring is done by type) and use @Component for exposing classes to the automatic wiring.

The situation described below arose while I tried to test my code.

Now to the problem:

Note: I use a different Spring Context for the Test environment.

I have a class FOO which is @Autowired but in the test context I want to use a different class of the same type MockFoo (extends FOO).

The Spring setup of course fails automatically due to multiple options for the Dependency Injection of the FOO class (both FOO and MockFOO comply to the Type check).

I am looking for a way to inject the test bean instead of the original bean.

I expected Spring to allow using the Context configuration file to override a bean injection or to order Spring not to autowire a specific bean.

BUT

All these options seem to exists only for the beans which were originally defined in the Spring Context Configuration file.

like image 781
Mark Avatar asked May 16 '10 10:05

Mark


People also ask

How do you override a Spring class?

Spring beans are identified by their names within an ApplicationContext. Therefore, bean overriding is a default behavior that happens when we define a bean within an ApplicationContext that has the same name as another bean. It works by simply replacing the former bean in case of a name conflict.

What will happen if I make @autowired as false?

By default, the @Autowired annotation implies that the dependency is required. This means an exception will be thrown when a dependency is not resolved. You can override that default behavior using the (required=false) option with @Autowired .

What is the actual use of @autowired @qualifier @component annotation?

There may be a situation when you create more than one bean of the same type and want to wire only one of them with a property. In such cases, you can use the @Qualifier annotation along with @Autowired to remove the confusion by specifying which exact bean will be wired.

What is the default mode of @autowired?

Autowire Disambiguation By default, Spring resolves @Autowired entries by type. If more than one bean of the same type is available in the container, the framework will throw a fatal exception. To resolve this conflict, we need to tell Spring explicitly which bean we want to inject.


2 Answers

Use ReflectionTestUtils to manually set the Mock in place of the autowired dependency (for that purpose your mock must not be spring managed, so that no ambiguity exists)

like image 172
Bozho Avatar answered Nov 16 '22 03:11

Bozho


I know this question is quite old but a I think an answer might still be useful for others.

Since you probably do not want to mix both Foo and MockFoo within your context, I would suggest to remove Foo from the component-scanning. This could be done for example by specifying include/exclude filters on the <context:component-scan>.

However if you are implementing unit tests, I would rather suggest not using a Spring context and just implementing "pure" unit tests by injecting mock-ups of the dependencies manually, so that you are only testing a single class. This can be achieved more easily by using a mocking framework like Mockito.

like image 30
Didier L Avatar answered Nov 16 '22 04:11

Didier L