How to override the behavior of Spring #Autowired - unit-testing

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.

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)

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.

I agree with Didier. Here is an example of how you can exclude the implementations that you want to mock in your test application context.
<context:component-scan base-package="com.company" >
<context:exclude-filter type="regex" expression="com\.abc\.service\.XDaoImpl"/>
</context:component-scan>
Include this application context in your test as follows :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={"classpath:/applicationContext-test.xml"})
public class MyTest {....}

Related

How to mock Kotlin class (final) using PowerMock?

I wish to know how can I mock kotlin final class with PowerMock so I can test it. I followed guide for testing Java final classes but I still got this error
Cannot subclass final class
Is there any way to do that?
With Mockito 2.1.0+ you can mock final classess as well. This feature is optional, so you have to enable it by adding Mockito extension.
To do this:
Create a file named org.mockito.plugins.MockMaker and place it under the resources/mockito-extensions directory in your test folder.
The file contains a single line: mock-maker-inline
You can find more information in Mockito documentation.
Just create interfaces for your classes. Than you can simply mock your classes using interface.

Using both Arquillian and PowerMock in the same JUnit test

I would like to use the features of both Arquillian and PowerMock in the same JUnit 4 test.
The problem is that both products are JUnit Runners which should be used with #RunWith, and this is not possible to use multiple #RunWith on the same test class, or to put multiple Runners class in the same #RunWith annotation.
Do you know any way to do that ?
You can use PowerMock without using the runner if you use the PowerMockRule (which is a TestRule). From the PowerMockRule:
Since version 1.4 it's possible to bootstrap PowerMock using a JUnit
Rule instead of using the PowerMockRunner and the RunWith annotation.
This allows you to use other JUnit runners while still benefiting from
PowerMock's functionality. You do this by specifying:
#RunWith(Arquillian.class);
public class MyTest {
#Rule
PowerMockRule rule = new PowerMockRule();
// Tests goes here
...
}
See also the answers to Junit Parameterized tests together with Powermock - how? and the following thread in the PowerMock google group: Using PowerMock without the RunWith?.
No, you either need to:
use one and create a test base class that does the things you wanted the other runner to do.
separate your test into multiple tests, each using different runners.
JUnit4 only supports one #RunWith annotation, and JUnit4's #RunWith annotation doesn’t accept multiple runners.
Reference: project13

mocking the return value of domainInstance.validate()

I am writing a spock unit test that tests a controller method.
The controller action under test instantiates a new domain instance object and
calls validate on it before it saves.
Is there anyway of mocking the call to domainInstance.validate() so I
can make it return whatever I want? Or do I have to hide this
instanciation and saving behind a service method to achieve this?
I do this this way, because within the context of a unit test for a
controller, the constraints of a domain object should not be involved.
I test those elsewhere (in the MyDomainClassTests, obviously). If I
wanted to take those into into account my test would be an integration
test.
If you didn't place the validate on the domain instance itself, but rather in a service,
you could let your controller take a Service in its constructor (or rather an interface of a service). Let that service handle the validation.
Now for your unittest of that controller, you would pass in a Mock of that interface(service) to the controller and configure the mock to return whatever you want.
For .net i can recommend Moq (http://code.google.com/p/moq/)
After a while I have come to the conclusion that what I wanted is rather tricky. If you're in a scenario where you don't have to use mockDomain(), you could add a groovy metaclass method and it's implementation (return true or false, whichever you want)
If you do need mockDomain() because you need to mock pre-existing instances you are out of options, at least for now because mockDomain() and fiddling with metaclass methods that mockDomain actually provides will not mix.

Mocking a datacontext for an object that has a dependency

I'm writing some unit tests in my project and I have a datacontext dependency on the controller containing the methods I'd like to test.
I'm using Ninject to inject the dependency and Moq to create my mock datacontext. My DI makes use of an interface IDataContext which my dbml impliments and is used through out the injection process.
In my unit test I'm creating my mock datacontext as follows:
var mock = new Mock<IDataContext>();
var myController = new MyController(mock.Object);
This throws a Object reference not set to an instance of an object. exception on the second line whilst executing the datacontexts constructor.
I'm clearly missing a fundamental piece in setting this up however most of the Moq examples I've seen involve some kind of test against the mocked object using Setup().
Am I going about this the right way? Should I be creating a mock of my IDataContext interface or something else?
haha,
the answer came while i was reading through emad's blog on unit testing in ASP.Net MVC.
I'm guessing that you didn't add the connection string to the app.config of your test project right? :)
And that's the database dependency way because you're still not mocking the database end.
So if you want to do that, you need to google up for some codes, there are a few ways to do that.
i find these few references below to be quite useful, but since i don't really have a need to mock the database end, i'm just using my test DB server for now.
link

Spring Test Framework and annotation-based autowiring Problem

I would like to use two different implementations for a DAO with Spring's testframework.
src.main.java
.businessobjects
\-User.java
.dao
\-IUserDAO.java
.daojpa
\-UserDAO.java
.daohibernate
\-UserDAO.java
The spring testcase in:
src.test.java.base:
package base;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/hibernate-beans.xml")
#Transactional
public abstract class SpringTestCase {}
And here is the error:
Caused by:
java.lang.IllegalStateException:
Annotation-specified bean name
'userDAO' for bean class
[jpadao.UserDAO]
conflicts with existing,
non-compatible bean definition of same
name and class
[jpaadao.UserDAO]
I have already tried to override the autowiring by using qualifiers, e.g.:
<bean class="jpaadao.UserDAO">
<qualifier value="jpaa"/>
</bean>
<bean class="jpadao.UserDAO">
<qualifier value="jpa"/>
</bean>
And then in the testcase wiring with
#Autowired
#Qualifier("jpa")
private IUserDAO userDAO;
but the error persists.
Two questions:
How can this problem be solved with annotation based configuration?
How can I run tests WITHOUT autowiring and annotations?
You're using beans without names so that Spring will try to come up with a name, this name may be based on the #Component annotation that you presumably have on your class, but it could also be the camelcased version of your the unqualified class name of your bean (in both cases they would turn out equal and that causes Spring to object).
Also, it seems you are mixing component scanning and xml configuration in a way that looks a bit odd to me.
There are many ways out of this, but most cleanly you would use only a single bean implementing the contract you're trying to fullfil. If you do need different implementations you should give them different and more discriptive names:
<bean id="jpaUserRepository" class="..JpaUserRepository"/>
This will give you more useful logging, even if the bean names are never used because you rely on auto wiring.
Do what Iwein suggested: name your implementation classes better (e.g., HibernateUserDao and JpaUserDao); or specify a unique bean name via the #Component or #Repository annotation on your UserDAO implementation classes.
You cannot currently run tests without autowiring. See this JIRA issue for details: https://jira.springsource.org/browse/SPR-6050
Regards,
Sam (author of the Spring TestContext Framework)
p.s. No, the problem you are facing is not related to SPR-4524.
You can try injecting the dependency by-name using the #Resource annotation. You will have to give names (ids) to the beans or use the default, which is the uncapitalized unqualified class name.
I've got it up and running now! However, I don't believe this is best practice. I simply excluded the path of the unwanted DAOs by writing into appContext.xml:
<context:component-scan base-package="test">
<context:exclude-filter type="regex" expression="test\.daohibernate.*"></context:exclude-filter>
</context:component-scan>
Any suggestions? Could this issue be related to http://jira.springframework.org/browse/SPR-4524 ?