如何决定在Java单元测试中模拟什么?

时间:2017-08-23 06:39:53

标签: unit-testing mocking mockito

我正在尝试使用Mockito为遗留代码编写单元测试。

但我无法理解如何嘲笑它。可以请一些帮助。

我面临的真正问题实际上是我无法决定如何决定嘲笑究竟是什么?下面是代码。我在YouTube上观看了很多视频并阅读了许多Mockito教程,但所有这些视频似乎都主要指导如何使用Mockito框架。

Mock的基本想法仍不清楚。如果您有更好的来源,请指导。我确实理解下面显示的代码并没有真正展示最好的编码实践。

    public class DataFacade {

    public boolean checkUserPresent(String userId){
        return getSomeDao.checkUserPresent(userId);
    }


    private SomeDao getSomeDao() {
        DataSource dataSource = MyDataSourceFactory.getMySQLDataSource();
        SomeDao someDao = new SomeDao(dataSource);
    }
}

2 个答案:

答案 0 :(得分:3)

嗯,顾名思义,单位测试测试一个单元。您应该模拟不属于该单元的任何内容,尤其是外部依赖项。例如,DAO通常是在测试中被测试的东西的一个很好的例子,其中测试中的类使用它,因为否则你在测试中真的会有实际的数据访问,使得它更慢并且更容易因外部而失败原因(例如,如果您的dao连接到DatasourceDatasource的目标(例如,数据库)可能已关闭,即使您要测试的单元实际上是非常好)。模拟DAO可以让你独立测试。

当然,你的代码很糟糕。为什么?您正在通过调用一些静态工厂方法在方法中创建所有内容。我建议使用依赖注入将DAO注入到您的外观中,例如......

public DataFacade(SomeDao someDao) {
   this.someDao = someDao;
}

这样,在实例化你的DataFacade时,你可以给它一个dao,这意味着,在你的测试中你可以给它一个模拟,例如......

@Test
public void testSomething() {
    SomeDao someDaoMock = Mockito.mock(SomeDao.class);
    DataFacade toTest = new DataFacade(someDaoMock);

    ...now you can prepare your mock to do something and then call the DataFace method
}

像Spring,Google Guice等依赖注入框架可以使这更容易管理,但第一步是阻止你的类创建自己的依赖项,但让依赖从外部给予它们,使整件事变得更好。

答案 1 :(得分:0)

您应该“模拟”您在方法中使用的内部对象。

例如,如果您为DataFacade->checkUserPresent编写单元测试,则应该模拟getSomeDao字段。

你有很多方法可以做到这一点,但基本上你可以让getSomeDao成为公共字段,或者从构造函数中获取它。在测试类中,使用模拟对象覆盖此字段。 在调用DataFacade->checkUserPresent方法之后,断言调用checkUserPresent()。

例如,如果你有这门课程:

public class StudentsStore
{
   private DbReader _db;

   public StudentsStore(DbReader db)
   {
      _db = db;
   }

   public bool HasStudents()
   {
      var studentsCount = _db.GetStudentsCount();
      if (studentsCount > 0)
         return true;
      else
         return false;
   }
}

在你的测试方法中:

var mockedDb = mock(DbReader.class);
when(mockedDb.GetStudentsCount()).thenReturn(1);

var store = new StudentsSture(mockedDb);

assertEquals(true,store.HasStudents());