【问题标题】:Mockito - Creating nested mock objectsMockito - 创建嵌套的模拟对象
【发布时间】:2013-11-17 17:22:08
【问题描述】:

我正在学习 Mockito。我在为嵌套对象创建模拟时遇到问题。见

public interface BaseManager {
    public Query createQuery(String queryString);
}

还有一个实现类

public class BaseManagerImpl implements BaseManager {
    @Autowired
    private SessionFactory sessionFactory;
    // ...
}

模块级休眠管理器,例如:

public interface RegistrationManager {
    @Transactional
    public List<Country> getCountries();
}

还有一个实现类

public class RegistrationManagerImpl implements RegistrationManager {
    @Autowired
    private BaseManager baseManager;
    // ...
}

现在我在创建模拟基础管理器时遇到了问题。我的测试课是:

 public class MockitoTest {
    private RegistrationManager registrationManager = new RegistrationManagerImpl();

    @Mock private BaseManager baseManager;

    @Mock private SessionFactory sessionFactory;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    //  baseManager.setSessionFactory(sessionFactory);
        registrationManager.setBaseManager(baseManager);
    }
    // ...
    // @Test
}

问题:sessionFactory 没有在 baseManager 中实例化。 请帮助创建模拟对象。提前致谢!

【问题讨论】:

  • “baseManager 内部的 NullPointerException”是什么意思?你已经模拟了你的 baseManager 对象——它不应该执行任何你没有存根的代码。在此示例中您没有显示更多内容;请发布实际的 JUnit 测试和 full 堆栈跟踪。

标签: java mockito


【解决方案1】:

您不能将SessionFactory 的mock 注入BaseManager 的mock。

当您在测试RegistrationManagerImpl 时,您只需要拥有BaseManager 中的mock。您可以使用方法存根,以便在从RegistrationManagerImpl 方法调用这些方法时,方法BaseManager 将返回存根值。所以,如果你有这样的RegistrationManagerImpl:

public class RegistrationManagerImpl implements RegistrationManager {
    @Autowired
    private BaseManager baseManager;
    // ...
    public String doSomething(){
         return baseManager.process();  
    }
}

你可以这样写你的MockitoTest:

public class MockitoTest {
    @InjectMocks
    private RegistrationManager registrationManager = new RegistrationManagerImpl();

    @Mock private BaseManager baseManager;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);

    }
    // ...
    @Test
    public void test() {
    when(baseManager.process()).thenReturn("hello");

    assertEquals("hello", registrationManager.doSomething());
    }
}

在测试BaseManager 时,您需要使用mock of SeesionFactory。

【讨论】:

    【解决方案2】:

    问题是您正在创建 BaseManager 的模拟,但只有 BaseManagerImpl 具有 SessionFactory 字段。 Mockito 不知道BaseManagerImpl。在您的代码中,您创建了两个完全相互独立的模拟。

    单元测试是关于测试一个单元。所以你应该分别测试BaseManagerImpl和RegistrationManagerImpl。

    所以你先测试BaseManagerImpl:

    public class BaseManagerImplTest {
    
        private BaseManagerImpl target;
    
        // ...
    }
    

    然后你测试RegistrationManagerImpl:

    public class RegistrationManagerImplTest {
    
        private RegistrationManagerImpl target;
    
        // ...
    }
    

    我建议您在测试类中为您的测试目标使用名称 target 或类似名称,因为这样会使您的代码更易于阅读。

    另一件事:如果你测试一个对象,它的所有依赖项都应该被模拟,但你不应该关心模拟的依赖项。您只需模拟他们的方法调用,例如:

    Mockito.when(myMock.someMethod()).thenReturn(someResultObject);
    

    【讨论】:

    • 你是绝对正确的。我们不应该担心 mock 的依赖关系。但是我有一个问题,我有服务 ServiceA.methodA() 正在调用 ServiceB.methodB(..),从 methodB(...) 它正在调用 ManagerC.serviceC(...)。在这种情况下,我只想模拟 ManagerC.serviceC(...) 并希望真正调用 ServiceB.methodB(..) 因为我不想模拟我的业务层。在这种情况下,我和问这个问题的人有同样的问题。我怎样才能做到这一点?
    • 我不明白这个。 real call 是什么意思?
    • 我的意思是 FROM 服务 (A.a1),我正在调用同一类 (A.a2) 的另一个服务,而后者又调用其他类的方法 (B. b1)我只想模拟这个(B.b1)。怎么可能?
    【解决方案3】:

    您必须将@InjectMocks 注释放在要测试和模拟由basemanger 或sessionFactory 调用的方法的类之前。

    public class MockitoTest {
        @InjectMocks
        private RegistrationManager registrationManager = new RegistrationManagerImpl();
    
        @Mock private BaseManager baseManager;
    
        @Mock private SessionFactory sessionFactory;
    
        @Before
        public void setup() {
            MockitoAnnotations.initMocks(this);
        //  baseManager.setSessionFactory(sessionFactory);
            registrationManager.setBaseManager(baseManager);
    
            Mockito.when(baseManager.yourMethod()).thenReturn(someObject);
        }
        // ...
        // @Test
    }
    

    希望这就是你要找的!

    【讨论】:

    • 这不是问题。检查我的答案。
    猜你喜欢
    • 1970-01-01
    • 2023-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多