简体   繁体   English

JUnit / Spring / Mockito-无法模拟从另一个实现ApplicationContextAware的类返回的类

[英]JUnit/Spring/Mockito - Unable to mock class returned from another class implementing ApplicationContextAware

I am new to Spring and JUnit. 我是Spring和JUnit的新手。 I need to mock a class which is derived from ApplicationContextAware class which is inside my toBeTested(getList) method. 我需要模拟从我的toBeTested(getList)方法内部的ApplicationContextAware类派生的类。 In the following short code snippet, I need to test the getList method in abc class. 在下面的简短代码段中,我需要在abc类中测试getList方法。

I am able to mock ModulesConfigRegistry because there is a setter for it. 我能够模拟ModulesConfigRegistry,因为有一个设置程序。 But I am not able to mock ModuleConfig and ListProvider. 但是我无法模拟ModuleConfig和ListProvider。 Both ModulesConfigRegistry and ModuleConfig have implemented ApplicationContextAware so it returns classes from bean. ModulesConfigRegistry和ModuleConfig都实现了ApplicationContextAware,因此它从Bean返回类。 ListProvider.getList(lst.getList in code) is the method which makes further calls up to database and is required to be mocked. ListProvider.getList(在代码中为lst.getList)是对数据库进行进一步调用的方法,需要对其进行模拟。 Appreciate your help in advance. 提前感谢您的帮助。 Code sample will be helpful as I am new to Spring and JUnit. 由于我是Spring和JUnit的新手,因此代码示例将很有帮助。

class abc { 

    private ModulesConfigRegistry modulesConfigRegistry; 

    public void setModulesConfigRegistry(ModulesConfigRegistry modulesConfigRegistry) { 
        this.modulesConfigRegistry = modulesConfigRegistry; 
    } 

    public List getList(String name, String moduleName) 
    { 
        ModuleConfig moduleConfig = modulesConfigRegistry.getModuleConfig(moduleName); 
        Object mlist = moduleConfig.getListProvider(name); 
        if(mlist instanceof ListProvider) 
        { 
            ListProvider lst = (ListProvider)mList; 
        } 
        return lst.getList("abc"); 
    } 
}

Maybe there is another more simple way to achieve this (not mandatory the best). 也许还有另一种更简单的方法来实现此目的(最好不是强制性的)。 In my experience I've used Reflection in Java when it's up to Unit-testing. 根据我的经验在进行单元测试之前,我曾在Java中使用过Reflection After all, to me the main purpose of the unit tests is to simply exercise smallest testable part and nothing more. 毕竟,对我而言,单元测试的主要目的是仅行使最小的可测试部分,仅此而已。 That's why I simply use my dummy-test-object and get/set fields/properties I need. 这就是为什么我只使用我的虚拟测试对象并获取/设置所需的字段/属性的原因。

But one thing that must be considered here is that reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects. 但是这里必须考虑的一件事是,反射允许代码执行在非反射代码中是非法的操作,例如访问私有字段和方法,使用反射可能会导致意外的副作用。 So if you know what your doing it's a good alternative. 因此,如果您知道自己在做什么,那是一个很好的选择。

Since you already using 由于您已经在使用

JUnit JUnit的

One very common use case in Java is the usage with annotations. Java中一种非常常见的用例是带注释的用法。 JUnit 4, for example, will use reflection to look through your classes for methods tagged with the @Test annotation, and will then call them when running the unit test. 例如,JUnit 4将使用反射来遍历类,以查找带有@Test批注的方法,然后在运行单元测试时调用它们。

If you want to consider it and use it - here you can find some good examples . 如果您想考虑并使用它-在这里您可以找到一些很好的例子

Cheers. 干杯。

One approach here is create mock objects for each object that you need to interact with ModuleConfig and ListProvider 这里的一个方法是为每一个对象,你需要与之交互的模拟对象ModuleConfigListProvider

@RunWith(MockitoJUnitRunner.class)
public class abcTest{

    @InjectMocks
    private abc abcInstance;

    @Mock
    private ModulesConfigRegistry modulesConfigRegistry ;

    @Test
    private voidTestGetList(){
    //Create the mock and interactions
    ModuleConfig moduleConfigMock = Mockito.mock(ModuleConfig.class);
    ListProvider listProviderMock =  Mockito.mock(ListProvider.class);
    ArrayList listToReturn = new ArrayList();
    Mockito.when(modulesConfigRegistry.getModuleConfig(Mockito.anyString())).thenReturn(moduleConfigMock);
    Mockito.when(moduleConfigMock.getListProvider(Mockito.anyString())).thenReturn(listProviderMock);
    Mockito.when(listProviderMock.getList(Mockito.anyString())).thenReturn(listProviderMock);
    //Call real method
    List resultList = abcInstance.getList("stringInput1", "stringInput2");
    //Make assertions
    } 
}

Basically you need to create mock objects for any of the instances that you get from a mock object and use mockito to define the result of its method. 基本上,您需要为从模拟对象获得的任何实例创建模拟对象,并使用模仿来定义其方法的结果。

Other options is create a new class that implements or is a subclass of the returned object type and override the methods. 其他选项是创建一个新类,该类实现或返回的对象类型的子类,并覆盖方法。

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

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