单元测试模拟注入

时间:2013-03-13 22:12:42

标签: java spring hibernate junit mockito

我正在尝试对我的类进行单元测试,并模拟DAO以提供可预测的结果。不过,看来我的DAO方法仍然被调用,因为我收到了一个休眠错误。

  

org.hibernate.exception.GenericJDBCException:找不到Station 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");
    }
}

2 个答案:

答案 0 :(得分:2)

我认为您的Service会在您的Dao中定义application-context.xml时被实例化,并且在您尝试将虚拟广告注入服务之前就会收到错误。

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

private MyDao myDao;

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

然后在你的测试中:

MyService myService = new Myservice(mockedDao);

答案 1 :(得分:1)

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

模拟一个对象不会阻止hibernate启动(因为你正在加载applicationContext.xml,所以hibernate将尝试连接到DB)。你的模拟 - 它只是一个测试实例的一个字段的POJO,而不是Spring bean或类的替代品。

如果你只想测试dao和服务类(创建明确的单元测试) - 从测试中删除Spring相关的注释并自己完成(创建模拟,创建服务,将模拟服务,并测试它)。 / p>

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

第三条道路 - 您的配置文件拆分成两个弹簧的配置文件(例如devtest)和实施嘲笑自己(把模拟到test,真正的Hibernate和DAO为{{ 1}})。

如果您不想使用Spring配置文件 - 可以将dev拆分为3个文件(对于普通bean,对于真正的DB bean,对于模拟)。

还有一种更性感的方法 - 使用springockito-annotations(但你仍需要避免加载hibernate)