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}

检测到不必要的存根。

  1. -> 在 service.DishServiceTest.example(DishServiceTest.java:35)
  2. -> 在 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 构造中使用它。