Reputation: 85
I'm having problems trying to unit test a maven multi-module project with Spring.
I've 4 modules:
application-core
application-data
application-service
application-web
This is my test, its in the application-core
module:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/config/application-context.xml")
public class TicketTest {
@Mock
ITicketDAO ticketDAO;
@Autowired
@InjectMocks
ITicketCore ticketCore;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testRegisterTicket_Ticket_NotUsed_isValid() {
Long ticketNumber = 0L;
when(ticketDAO.getTicket(anyLong())).thenReturn(null);
final boolean isValidTicket = ticketCore.validateTicket(ticketNumber);
assertTrue(isValidTicket);
}
}
And here is the implementation:
@Component
@Scope("prototype")
public class TicketCore implements ITicketCore{
private ITicketDAO ticketDao;
@Autowired
public TicketCore(ITicketDAO ticketDao) {
this.ticketDao = ticketDao;
}
@Override
public boolean validateTicket(Long ticketNumber) {
ITicket ticket = ticketDao.getTicket(ticketNumber);
return ticket != null;
}
}
Interface:
public interface ITicketDAO {
ITicket getTicket(Long ticketNumber);
}
Implementation of ITicketDAO
its on the application-data
module:
@Service
public class TicketDAO implements ITicketDAO {
@Override
public ITicket getTicket(Long ticketNumber) {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
}
I'm having problems testing this code because the context doesn't find the implementation of ITicketDAO
. It's seems obvious, because when the test are running, JUnit doesn't care about putting in the classpath the "others modules".
Spring throws BeanCreationException
for obvious reasons.
Am I right?
So I would like to test my project without Spring getting in the tests' way.
What could I do to get my tests run w/o any problem???
I've created dummy classes in the test folder/packages, and it works, but...
I would eventually have ALL the external implementations in my application-core
module's test folder.
There is a better way?
Thanks in advance.
UPDATE:
application-data
application-service
application-web
all of them depends on application-core
. Spring successfully inject TicketCore
(application-core
). What I want is to give Spring "something" (a dummy class) to inject in ITicketDAO
just to run the test.
<beans>
<context:component-scan base-package="ve.gov.imat.transimat" />
<context:annotation-config />
<aop:config proxy-target-class="true" />
</beans>
Upvotes: 3
Views: 3702
Reputation: 3667
If I've understood you well your problem is your context file references a class you don't have available in your test classpath.
In principle tests shouldn't need the implementation of any collaborator to work, only the one of the sut.
One solution is to create an application-test-context.xml file under your test/resources folder to be used in your test instead of the production one. Within this file you can create the mocks of your collaborators
<!-- Mock service for splitting jobs -->
<bean factory-bean="mockControl" factory-method="createMock"
primary="true">
<constructor-arg value="net.compart.docpilot.model.service.JobSplitService" />
</bean>
Upvotes: 0
Reputation: 77234
Pretend that each Maven module is a completely separate project. Put tests specifically of each module's code inside it, and add integration tests in the module where all of the dependencies necessary to run them have been included.
You haven't provided any information on the dependencies between your modules, but it appears that the problem you're running into is that you need some implementation of an interface for testing purposes, but your production bean is defined in another module. This is what mocking frameworks like EasyMock and Mockito are for; they allow you to write simple placeholder implementations so that you can test TicketCore
specifically, and it's a good idea to use them even when the real implementation is available so that you can be sure you're just testing one component at a time.
In TicketTest
, you're correctly defining your Mockito mock for ITicketDAO
, but your TicketCore
is still trying to autoacquire the bean from Spring, even though you haven't registered it. Either manually register your bean into the test context, or place the definition for the mock in an @Configuration
in src/test
.
Upvotes: 3