简体   繁体   English

如何测试调用父类受保护(不需要的)方法的方法?

[英]How can I test a method which invoke protected (unwanted) methods of parent class?

I'm stuck in a very weird case.我被困在一个非常奇怪的案例中。 I have some specific code which I need to test.我有一些需要测试的特定代码。 Here it is:这里是:

public class A {

    /*
     * The real method of real class is so big that I just don't want to test it.
     * That's why I use throwing an exception.
     */
    protected void method(Integer result) {
        throw new RuntimeException("Oops!");
    }

    protected <T> T generifiedMethod(String s, T type) {
        throw new RuntimeException("Oops!");
    }

    protected void mainMethod(Integer value) {
        throw new RuntimeException("Oops!");
    }
}

I also have a child class:我也有一个子类:

public class B extends A {

    @Override
    protected void mainMethod(Integer value) {
        if (value == 100500) {
            Integer result = super.generifiedMethod("abc", 100);
            super.method(result);
        }
        super.mainMethod(value);
    }
}

I need to cover the child class with tests.我需要用测试来覆盖子类。

I was trying a lot of combinations with PowerMockito, but none of them can verify invocation of protected methods of parent class.我尝试了很多与 PowerMockito 的组合,但没有一个可以验证父类受保护方法的调用。 Also, I have a restriction on use only Mockito, PowerMockito and TestNG.另外,我对仅使用 Mockito、PowerMockito 和 TestNG 有限制。

Here is my test code (one of variants):这是我的测试代码(变体之一):

@Test
public void should_invoke_parent_logic_methods_of_A_class() throws Exception {

    /* Given */
    A aSpy = PowerMockito.spy(new A());

    PowerMockito.doReturn(250).when(aSpy, "generifiedMethod", "abc", 100);
    PowerMockito.doNothing().when(aSpy, "method", 250);
    PowerMockito.suppress(method(A.class, "mainMethod", Integer.class));

    /* When */
    aSpy.mainMethod(100500);

    /* Then */
    /**
     * Here I need to verify invocation of all methods of class A (generifiedMethod(), method(),
     * and mainMethod()). But I don't need them to be invoked because their logic is unwanted
     * to be tested in case of tests for class B.
     */
}

I would be appreciate for any suggestions how to test class B. Thanks.对于如何测试 B 类的任何建议,我将不胜感激。谢谢。

Update更新

If I add into Then section this code如果我添加到Then部分此代码

Mockito.verify(aSpy, times(3)).mainMethod(100500);
Mockito.verify(aSpy, times(1)).generifiedMethod("abc", 100);
Mockito.verify(aSpy, times(1)).method(250);

It gives me the following error message:它给了我以下错误消息:

Wanted but not invoked:
a.generifiedMethod("abc", 100);

Did you consider variant to change design of your classes and use composition instead of inheritance ?您是否考虑使用变体来更改类的设计并使用组合而不是继承? Then you will be able to just mock / spy instance of class A and inject it to instance of class B. In such case you will be able to configure whatever behavior that you need.然后,您将能够模拟/监视类 A 的实例并将其注入到类 B 的实例中。在这种情况下,您将能够配置您需要的任何行为。

I really not sure doCallRealMethod() will make trick for you, cause you have option to mock method or invoke real one, but not both simultaneously.我真的不确定 doCallRealMethod() 会为你做伎俩,因为你可以选择模拟方法或调用真正的方法,但不能同时调用。

I think you are in a case where you should not use a mock library, but revert to the old specialized stub mode. 我认为你不应该使用模拟库,而是恢复到旧的专用存根模式。

You have to create a specialized A that has the following functionnalities : 您必须创建具有以下功能的专用A:

  • note that methods method , generifiedMethod and mainMethod have been called 请注意,已调用方法methodgenerifiedMethodmainMethod
  • reset the above indicators 重置上述指标
  • give read access to the above indicators. 提供对上述指标的读取权限。

You can then construct your tests with Junit or TestNG. 然后,您可以使用Junit或TestNG构建测试。 The main problem that remain IMHO is that you probably will have to use a custom build procedure to load the A stub class and not the real A. 恕我直言的主要问题是你可能必须使用自定义构建过程来加载A存根类而不是真正的A.

If I understood you correctly, you want to test the method 'mainMethod' from class B. So, you should mock an object from class B, and not one from class A. Try this:如果我理解正确,您想测试 B 类中的方法“mainMethod”。因此,您应该模拟 B 类中的对象,而不是 A 类中的对象。试试这个:

/* Given */
B b = Mockito.mock(B.class);

//use this to skip the method execution
Mockito.doNothing().when(b).generifiedMethod(Mockito.anyString(), Mockito.any());
Mockito.doNothing().when(b).method(Mockito.anyInt());

//or use this to return whatever you want when the methods are called
Mockito.doReturn(new Object()).when(b).method(Mockito.anyInt());
Mockito.doReturn(new Object()).when(b).generifiedMethod(Mockito.anyString(), Mockito.any());

Then you can call the mainMethod from B, already knowing what the other methods will return.然后你可以从 B 调用 mainMethod,已经知道其他方法将返回什么。

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

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