【问题标题】:Java Mockito is hitting real method rather than using mocked methodJava Mockito 正在使用真实方法而不是使用模拟方法
【发布时间】:2019-10-15 10:15:12
【问题描述】:

我的 mockito 方法是使用真正的方法,而不是调用模拟的方法。您的意见会有所帮助

Java 代码。

public class CheckUser {
    private final UserDao userDao;

    public CheckUser (final String domain){
        userDao = new UserDao(domain);
    }

    public IUser getExistingUser(){
            if (userDao == null) {
                throw new RuntimeException("userDao is null");
            }
            IUser existingUser = userDao.getExistingUser();
            if (existingUser == null) {
                throw new RuntimeException("ExistingUser is null");
            }
            return existingUser;
    }
}

这是我的 JUnit 测试代码。

    @Test
    public void testExistingUser() {
        UserDao mockUserDao = mock(UserDao.class);
        when(mockUserDao.getExistingUser()).thenReturn(getExistingTestUser());
    }

    private UserDao getExistingTestUser(() {
        return ExistingUserImpl.Builder(). //withfield methods. build();
    }

我创建这个模拟对象仅用于测试目的。这只是返回由 IUser 实现的模拟 MockedExistingUserImpl 对象。

public class MockedExistingUserImpl implements IUser {
    //fields
    //overriding getter methods for all fields
    //Builder for  ExistingUserImpl
}

当我在我的代码中调用 userDao.getExistingUser() 时,我希望返回模拟的现有用户对象,但由于域连接,它正在命中真实方法并且测试失败。我们不建立域连接来运行 Junits。任何输入表示赞赏。谢谢!

【问题讨论】:

  • "当我在我的代码中调用 userDao.getExistingUser() 时" > 你能发布调用它的单元测试代码吗?
  • 这是一个用于现场使用的类,还是一个用于测试的类?因为它似乎是一个供实时使用的类,并且在该类中内置了测试。
  • CheckUser 只是现场使用的类。其余的都是为了测试目的而创建的
  • @DatNguyen Nguyen 这是我的 Junit 代码 @Test public void testExistingUser(){ UserDao mockUserDao = mock(UserDao.class); when(mockUserDao.getExistingUser()).thenReturn(getExistingTestUser()); }

标签: java unit-testing mocking mockito junit4


【解决方案1】:

答案是阅读有关 Mockito 的教程并遵循该教程。你犯了一个典型的错误:你创建了一个模拟对象,但是你没有做任何事情让你的生产代码使用这个模拟对象。

仅仅做一个 mock(YourClass) 并不会神奇地改变你的生产代码中的 new() 以返回一个模拟实例。

您需要将模拟实例注入到被测代码中。例如,通过使用 @InjectMock 注释。

如需良好的介绍,请参阅 https://www.baeldung.com/Mockito-annotations 示例。

请注意:正如现在所写的那样,您将很难使用 Mockito 进行测试。由于直接调用 new(),您需要 PowerMock(ito) 来测试它。所以:学习如何使用 Mockito,然后重新编写你的生产代码,使其易于测试。 (转向 PowerMock 将是错误的策略)。

【讨论】:

  • 始终建议在适用的情况下使用构造函数注入。
  • @chrylis 这值得商榷。仅仅为了测试而使用伸缩构造函数......好吧:现实世界的解决方案可能是使用 real 依赖注入,而不是基于额外的 ctor,而是一个真正的依赖注入系统。
【解决方案2】:

您的错误在于破坏了“依赖注入”原则。

不要使用new 运算符 - 在上面的级别创建 UserDao 并使用注入。

public class CheckUser {
    private final UserDao userDao;

    public CheckUser (final UserDao usedDao) {
        this.userDao = userDao;
    }

    public IUser getExistingUser() {
        if (userDao == null) {
            throw new RuntimeException("userDao is null");
        }
        IUser existingUser = userDao.getExistingUser();
        if (existingUser == null) {
            throw new RuntimeException("ExistingUser is null");
        }
        return existingUser;
    }
}

现在您可以通过以下方式测试您的代码:

@Test
public void testExistingUser() {
    UserDao mockUserDao = mock(UserDao.class);
    when(mockUserDao.getExistingUser()).thenReturn(getExistingTestUser());

    CheckUser checkUser = new CheckUser(mockUserDao);
    IUser iUser = checkUser.getExistingUser();

    // assertions here
}

private UserDao getExistingTestUser(() {
    return ExistingUserImpl.Builder(). //withfield methods. build();
}

【讨论】:

  • 感谢您的回复。嗯,这种方法是有道理的。使用 new 运算符是个坏主意。如果我在单独的 java 测试类中创建我的 Junits,这对我有用。但是,我需要使用 parentTestplan 类创建测试计划。所以,如果我在现有的父测试计划中使用它,它就会失败。这真是令人沮丧。
猜你喜欢
  • 1970-01-01
  • 2023-03-22
  • 2017-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
相关资源
最近更新 更多