Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I unit-test Maven multi-module Spring app?

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>
like image 389
Julio Indriago Avatar asked Mar 25 '26 19:03

Julio Indriago


1 Answers

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.

like image 163
chrylis -cautiouslyoptimistic- Avatar answered Mar 28 '26 09:03

chrylis -cautiouslyoptimistic-



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!