2013-03-13 153 views
1

我想单元测试我的类,并模拟DAO提供可预测的结果。不过,看起来我的DAO方法仍然被调用,因为我收到一个休眠错误。单元测试模拟注入

org.hibernate.exception.GenericJDBCException:找不到站点TST。

这个错误是我的数据库不包含TST的结果,但不应该因为我嘲笑DAO而被调用?我如何嘲笑这个调用,以至于数据库没有被击中。

下面是我如何设置我的模拟

@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"); 
    } 
} 

回答

1

为先,而不是Field f = MyService.class.getDeclaredField("dao");检查PowerMock(检查Whitebox

嘲弄一个对象不会阻止休眠启动(因为你正在加载applicationContext.xml,所以休眠会尝试连接到数据库)。你的模拟 - 它只是一个测试实例的一个字段的POJO,而不是Spring bean或类的替代品。如果你只想测试dao和服务类(创建清晰的单元测试) - 从测试中删除与Spring相关的注释并自行完成(创建模拟,创建服务,将模拟服务和测试)。

如果您想用Spring上下文测试您的应用程序(创建集成测试) - 创建H2 in-memory database进行休眠并测试您的服务(不要忘记在@After中清除它)。

第三条道路 - 分割你的配置文件到两个弹簧的配置文件(例如devtest)和实施嘲笑自己(把模拟到test,真正的Hibernate和DAO来dev)。

如果你不想使用Spring配置文件 - 可以将applicationContext.xml分为3个文件(对于普通的bean,对于真正的DB beans,对于mock)。

而且一个更性感的方式 - 使用springockito-annotations(但你仍然需要避免休眠加载)

+0

不幸的是H2不是一个选项。至于“自己做”,我的服务还有许多其他的bean需要自动注入,这使得这种方法不切合实际。真的没有办法完全嘲弄道? – 75inchpianist 2013-03-13 22:46:29

+0

你可以。首先,将你的hibernate相关的xml配置移到一些(“dev”)Spring配置文件(谷歌的“spring配置文件”)。然后创建dao的存根(模拟)实现并将其放到“测试”配置文件中。在测试中添加@ActiveProfiles(“test”)注释之后(您还需要在常规应用程序启动时激活“dev”配置文件)。如果你不喜欢配置文件 - 在3个文件(applicationContext.xml,dev.xml,mock.xml)中拆分配置 – 2013-03-13 22:56:25

+0

并且还检查 - https://bitbucket.org/kubek2k/springockito/wiki/Home – 2013-03-13 22:59:01

2

我认为你Service被弹簧实例与Daoapplication-context.xml定义,你会得到你的错误之前,你甚至尝试在你的服务以注入模拟。

我喜欢用来测试我的服务的一件事是一个Autowired构造函数,然后在我的测试中,我没有通过spring实例化我的服务,但使用构造函数和模拟。

private MyDao myDao; 

@Autowired 
public MyService(MyDao myDao){ 
this.myDao = myDao; 
} 

然后在您的测试:

MyService myService = new Myservice(mockedDao); 
+0

错误肯定来后我注入我的模拟。我可以通过逐步调试器来判断 – 75inchpianist 2013-03-13 22:41:38

+0

您的服务是否包含其他人dao? – benzonico 2013-03-13 22:43:23

+0

不只是一个,但它确实包含我需要的其他bean AutoInjected – 75inchpianist 2013-03-13 22:45:33