Mockito,对象未被模拟
Mockito, object is not mocked
下面是我测试的简单class。它看起来很奇怪,但出于某种原因我把它简化了。
public class DishService {
DaoFactory daoFactory = DaoFactory.getInstance();
public void exampleMethod() {
System.out.println(daoFactory);
DishDao dishDao = daoFactory.createDishDao();
System.out.println(dishDao.findById(1));
}
}
这是 DaoFactory class
public abstract class DaoFactory {
private static DaoFactory daoFactory;
public abstract UserDao createUserDao();
public abstract DishDao createDishDao();
public abstract OrderDao createOrderDao();
public static DaoFactory getInstance() {
if (daoFactory == null) {
synchronized (DaoFactory.class) {
daoFactory = new JDBCDaoFactory();
}
}
return daoFactory;
}
}
这是我的测试class
@ExtendWith(MockitoExtension.class)
class DishServiceTest {
@Spy
DishService dishService;
@Mock
DishDao dishDao;
@Mock
DaoFactory daoFactory;
@Test
void example() {
MockedStatic<DaoFactory> daoFactoryDummy = Mockito.mockStatic(DaoFactory.class);
daoFactoryDummy.when(DaoFactory::getInstance).thenReturn(daoFactory);
Mockito.when(daoFactory.createDishDao()).thenReturn(dishDao);
when(dishDao.findById(1)).thenReturn(new Dish());
dishService.exampleMethod();
}
问题是 daoFactory 根本没有被模拟。如您所见,我 return new Dish(默认构造函数),因此 System.out.println()
应该显示一个空对象,但它连接到 DB 并从真正的 daoFactory 获取对象。
这是我在控制台中看到的
菜肴{名称='dadawd'、描述='wdadwad2'、类别=饮料、价格=23131.00、图片文件名='FIRSTSnacksAsDaypart_1.jpg'、订单项=null}
检测到不必要的存根。
- -> 在 service.DishServiceTest.example(DishServiceTest.java:35)
- -> 在 service.DishServiceTest.example(DishServiceTest.java:36)
您可以在屏幕上看到 35 和 36 行代码。
你在什么时候 initialize/create dishService 对象?在@BeforeTest 中?
因为你在 dishService
对象上有一个字段 daoFactory
,所以 DaoFactory.getInstance()
在你模拟它的方法之前被调用,因为它在你创建 dishService
对象时被调用。
所以你需要创建 dishService 对象在你已经模拟工厂静态方法之后,在@Test 方法中。
或者另一种方法是直接在 dishService.exampleMethod()
.
中使用 DaoFactory.getInstance()
在这两种情况下:首先模拟静态方法,然后调用它。
另外不要忘记关闭静态模拟,甚至更好:在 try-with-resources 构造中使用它。
下面是我测试的简单class。它看起来很奇怪,但出于某种原因我把它简化了。
public class DishService {
DaoFactory daoFactory = DaoFactory.getInstance();
public void exampleMethod() {
System.out.println(daoFactory);
DishDao dishDao = daoFactory.createDishDao();
System.out.println(dishDao.findById(1));
}
}
这是 DaoFactory class
public abstract class DaoFactory {
private static DaoFactory daoFactory;
public abstract UserDao createUserDao();
public abstract DishDao createDishDao();
public abstract OrderDao createOrderDao();
public static DaoFactory getInstance() {
if (daoFactory == null) {
synchronized (DaoFactory.class) {
daoFactory = new JDBCDaoFactory();
}
}
return daoFactory;
}
}
这是我的测试class
@ExtendWith(MockitoExtension.class)
class DishServiceTest {
@Spy
DishService dishService;
@Mock
DishDao dishDao;
@Mock
DaoFactory daoFactory;
@Test
void example() {
MockedStatic<DaoFactory> daoFactoryDummy = Mockito.mockStatic(DaoFactory.class);
daoFactoryDummy.when(DaoFactory::getInstance).thenReturn(daoFactory);
Mockito.when(daoFactory.createDishDao()).thenReturn(dishDao);
when(dishDao.findById(1)).thenReturn(new Dish());
dishService.exampleMethod();
}
问题是 daoFactory 根本没有被模拟。如您所见,我 return new Dish(默认构造函数),因此 System.out.println()
应该显示一个空对象,但它连接到 DB 并从真正的 daoFactory 获取对象。
这是我在控制台中看到的
菜肴{名称='dadawd'、描述='wdadwad2'、类别=饮料、价格=23131.00、图片文件名='FIRSTSnacksAsDaypart_1.jpg'、订单项=null}
检测到不必要的存根。
- -> 在 service.DishServiceTest.example(DishServiceTest.java:35)
- -> 在 service.DishServiceTest.example(DishServiceTest.java:36) 您可以在屏幕上看到 35 和 36 行代码。
你在什么时候 initialize/create dishService 对象?在@BeforeTest 中?
因为你在 dishService
对象上有一个字段 daoFactory
,所以 DaoFactory.getInstance()
在你模拟它的方法之前被调用,因为它在你创建 dishService
对象时被调用。
所以你需要创建 dishService 对象在你已经模拟工厂静态方法之后,在@Test 方法中。
或者另一种方法是直接在 dishService.exampleMethod()
.
DaoFactory.getInstance()
在这两种情况下:首先模拟静态方法,然后调用它。
另外不要忘记关闭静态模拟,甚至更好:在 try-with-resources 构造中使用它。