简体   繁体   English

Mockito - 创建嵌套的模拟对象

[英]Mockito - Creating nested mock objects

I'm learning Mockito. 我正在学习Mockito。 I am facing problem while creating mock for nested objects. 我在为嵌套对象创建模拟时遇到问题。 See 看到

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

and an implementation class for that 和一个实现类

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

Module level hibernate manager, for example: 模块级别的hibernate管理器,例如:

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

and an implementation class for that 和一个实现类

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

Now I'm facing problem in creating mocked base manager. 现在我在创建模拟基础管理器方面遇到了问题。 My test class is: 我的测试类是:

 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
}

Problem: sessionFactory is not instantiated inside baseManager. 问题: sessionFactory未在baseManager中实例化。 Please help creating mock object. 请帮助创建模拟对象。 Thanks in advance! 提前致谢!

You have to put the @InjectMocks annotation before class you want to test and mock the methods which are called by the basemanger or sessionFactory. 您必须在要测试的类之前放置@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
}

Hope this is it you're looking for! 希望这是你正在寻找的!

The problem is that you are creating a mock of BaseManager but only BaseManagerImpl has a SessionFactory field. 问题是您正在创建BaseManager的模拟,但只有BaseManagerImpl具有SessionFactory字段。 Mockito doesn't know about BaseManagerImpl . Mockito不了解BaseManagerImpl In your code you create two mocks which are completely independent of each other. 在您的代码中,您创建两个完全独立的模拟。

Unit tests are about testing an unit . 单元测试是关于测试一个单元 So you should test BaseManagerImpl and RegistrationManagerImpl separately. 所以你应该分别测试BaseManagerImplRegistrationManagerImpl

So you test BaseManagerImpl first: 所以你首先测试BaseManagerImpl

public class BaseManagerImplTest {

    private BaseManagerImpl target;

    // ...
}

then you test RegistrationManagerImpl : 然后你测试RegistrationManagerImpl

public class RegistrationManagerImplTest {

    private RegistrationManagerImpl target;

    // ...
}

I suggest that you should use the name target or something similar for your test target in your test class becaues it will make your code much more easier to read. 我建议您在测试类中使用名称target或类似的测试目标,因为它会使您的代码更容易阅读。

Another thing: If you test an object all of its dependencies should be mocked but you shouldn't care about the mocks' dependencies. 另一件事:如果你测试一个对象,它的所有依赖项都应该被模拟,但你不应该关心模拟的依赖项。 You just mock their method invocations like: 你只是模拟他们的方法调用,如:

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

You cannot inject a mock of SessionFactory into a mock of BaseManager . 你不能注入一个mockSessionFactorymockBaseManager

As you are testing RegistrationManagerImpl , you just need to have a mock of BaseManager . 在测试RegistrationManagerImpl ,您只需要mock BaseManager You can use method stubbing so that the methods BaseManager will return the stubbed values when those methods are called from RegistrationManagerImpl methods. 您可以使用方法存根,以便在从RegistrationManagerImpl方法调用这些方法时,方法BaseManager将返回存根值。 So, if you have a RegistrationManagerImpl as this: 所以,如果你有一个RegistrationManagerImpl

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

you can write your MockitoTest as this: 你可以写下你的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());
    }
}

And while testing BaseManager , there you need to use mock of SeesionFactory . 在测试BaseManager ,你需要使用SeesionFactory mock

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM