Java Mockito - 创建嵌套的模拟对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19812651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 20:24:19  来源:igfitidea点击:

Mockito - Creating nested mock objects

javamockito

提问by masT

I'm learning Mockito. I am facing problem while creating mock for nested objects. See

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

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:

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

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.Please help creating mock object. Thanks in advance!

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

回答by gmeiner.m

You have to put the @InjectMocksannotation 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!

希望这就是你要找的!

回答by Adam Arold

The problem is that you are creating a mock of BaseManagerbut only BaseManagerImplhas a SessionFactoryfield. Mockito doesn't know about BaseManagerImpl. In your code you create two mocks which are completely independent of each other.

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

Unit tests are about testing an unit. So you should test BaseManagerImpland RegistrationManagerImplseparately.

单元测试是关于测试一个单元。所以,你应该测试BaseManagerImplRegistrationManagerImpl分开。

So you test BaseManagerImplfirst:

所以你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 targetor 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);

回答by Debojit Saikia

You cannot inject a mockof SessionFactoryinto a mockof BaseManager.

您不能将 a mockofSessionFactory注入 a mockof BaseManager

As you are testing RegistrationManagerImpl, you just need to have a mockof BaseManager. You can use method stubbing so that the methods BaseManagerwill return the stubbed values when those methods are called from RegistrationManagerImplmethods. So, if you have a RegistrationManagerImplas this:

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

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

you can write your MockitoTestas 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 mockof SeesionFactory.

而在测试BaseManager中,你需要使用mockSeesionFactory