Reputation: 4102
I am trying to unit test my class, and mock the DAO to provide predictable results. Still, it would appear that my DAO's method is still being called as I receive a hibernate error.
org.hibernate.exception.GenericJDBCException: Station TST not found.
This error is a result of my database not containing TST, but shouldnt this not even be called since I mocked the DAO? How do I mock the call so that the database isn't even hit.
Here's how I set up my mock
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class MyServiceTest{
@Autowired
private MyService service;
private MyDAO dao;
private LinkedList objs;
@Before
public void init() throws SecurityException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException {
// mock the dao for predictable results
dao = mock(MyDAO.class);
when(dao.myDBCall(anyString(), any(Date.class))).thenReturn(legs);
Field f = MyService.class.getDeclaredField("dao");
f.setAccessible(true);
f.set(service, dao);
}
@Test
public void testCall() {
// construct our sample leg data
legs = new LinkedList();
//fill in my stub data i want to return
Collections.shuffle(legs);
List results = service.testingCall("TST", new Date()); // this fails because service is using the dao, but it is making a call to the DB with this garbage 'Test' param rather than just returning 'legs' as stated in my when clause
assertThat(results, not(nullValue()));
}
@Test
public void testGetGates() {
// fail("Not yet implemented");
}
@Test
public void testGetStations() {
// fail("Not yet implemented");
}
}
Upvotes: 1
Views: 1930
Reputation: 3775
For first, instead of Field f = MyService.class.getDeclaredField("dao");
check for PowerMock (check for Whitebox
)
Mocking one object will not prevent hibernate to start (because you are loading applicationContext.xml
, so hibernate will try to connect to DB). Your mock - it is just a POJO at one field of one test instance, not a Spring bean or replacement for class.
If you want to test only dao and service classes (create clear unit test) - remove Spring related annotations from test and do it on your own (create mock, create service, put mock to service, and test it).
If you want test your application with Spring context (create integration test) - create H2 in-memory database for hibernate and just test your service (don't forget to clear it in @After
).
Third way - split your configuration file into two Spring profiles (for example dev
and test
) and implement mock yourself (put mock to test
, real hibernate and dao to dev
).
If you dont want use Spring profiles - it is possible to split applicationContext.xml
into 3 files (for common beans, for real DB beans, for mocks).
And one more sexy way - use springockito-annotations (but you still need to avoid hibernate be loaded)
Upvotes: 1
Reputation: 10833
I think that your Service
is instantiated by spring with your Dao
defined in your application-context.xml
and you get your error before you even try to inject your mock in your service.
One thing I like to use to test my services is an Autowired
constructor and then in my tests I do not instantiate my services by spring but using the constructor and the mock.
private MyDao myDao;
@Autowired
public MyService(MyDao myDao){
this.myDao = myDao;
}
And then in your test :
MyService myService = new Myservice(mockedDao);
Upvotes: 2