首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >处理Mockit,类似于来自JMockit的JMockit

处理Mockit,类似于来自JMockit的JMockit
EN

Stack Overflow用户
提问于 2019-10-25 15:43:55
回答 1查看 1.2K关注 0票数 0

我想做一些类似于来自JMockit的“JMockit”的事情,但是使用Mockito。

我想控制扩展我要测试的类的类的方法的行为。但是我有一个问题,就是方法是私有的,所以我想我不能使用Mockito,而需要使用PowerMock。

问题

代码语言:javascript
复制
Class A extends B{...}

Class B {
  private Header generateHeaderForServiceCall(c,d,f,g,h,j){...}
} 

在我的类ATest中{ In @在我想要模拟generateHeaderForServiceCall(.)之前只返回为我创建的默认标题。}

因此,使用JMockit就像:

代码语言:javascript
复制
new MockUp<Controller>() {
  @Mock
  private Header generateHeaderForServiceCall(...) {
    return defaultHeader;
 }
};

我将更好地说明我的情况:

代码语言:javascript
复制
public class B {
    private Header generateHeaderForServiceCall(Input A, Input B, Input c, Input D) throws ServiceException {
......
//do stuff
return header} 
}


public class A extends B {
    @Override
    public Response process(Request request) throws SOAException {
               //do stuff
        try {
            method_i_want_to_test(Input A, Input B);

            } catch (Exception t) {
                  throwCorrectException(t, logger);
     }
        return response;
 }

    protected Dossier method_i_want_to_test(Input A, Input B) throws 
       SOAException {
        ... //do stuff
        **Header** **header** = generateHeaderForServiceCall(Input A, Input 
             B,Input c, Input D);**

         // **doLogic** with header returned and return the result
    }
}

我想做的事:

代码语言:javascript
复制
private A aTest;
    @Before
    public void setUp() throws Exception {

        PowerMockito.mock(aTest);

 PowerMockito.doReturn(defaultHeader).when(aTest,"generateHeaderForServiceCall", params);
    }

因此,当我转到method_i_want_to_test并调用generateHeaderForServiceCall时,我只想获得一个默认的标头,而忽略该方法的输入和逻辑。我想模拟这个方法,但是它是私有的/受保护的。

  • 所以,我能和莫基托一起用吗?
  • 我需要用PowerMock吗?
  • 我能用Mockito和PowerMockit在一起吗?

-

所以,我的classA,我要测试的是:

代码语言:javascript
复制
    package mypackage;

    import package.ClassB;

    @Service
    public class ClassA extends ClassB implements Xinterface {


        @Inject
        public ClassA(InputA inputA,  InputB inputB,InputC inputC,  InputD inputD) {
            ...
        }

        @Override
        public ClassAResponse process(ClassARequest request) throws SOAException {
            ClassAResponse response = initResponse(inputA, request, new ClassAResponse());
            ClassAInput input = request.getInput();
            ClassAOutput output = new ClassAOutput();
            response.setOutput(output);

            try {

                /*  */
                method_i_want_to_test(request.getHeader(), numberInput);

            } catch (Exception t) {
                throwCorrectException(t, logger);
            }
            return response;
        }

        protected Dossier method_i_want_to_test(Header srcHeader, Long numberInput) throws SOAException {

            Header header = generateHeaderForServiceCall(inputA,srcHeader,inputF,inputJ,inputK);

            OtherServiceRequest request = new OtherServiceRequest();
            OtherServiceInput input = new OtherServiceInput();
            input.setNumber(numberInput);
            request.setInput(input);
            request.setHeader(header); // So, you can see the i need the result of generateHeaderForServiceCall method

            OtherServiceResponse response = OtherService.process(request);
            assertSucessfullResponse(response, "OtherService");

            return response;

        }

    }

包含私有和受保护方法的ClassB是:

代码语言:javascript
复制
    package otherPackage;
    ...

    public class ClassB {

        private Header generateHeaderForServiceCall(InputA inputA,Header srcHeader,InputF inputF,InputJ inputJ,InputK inputK) throws ServiceException {

            String[] nameInfo = QNameUtil.getServiceQNameInfo(inputA);

            String serviceVersion = auxMethod(inputJ, inputF);

            //... do more stuff

            return result;
        }
    }

以及我的测试类,其中我使用PowerMock测试私有方法,如果该方法受到保护,则使用Mockito进行测试。在此之后,我将解释我在运行这两个测试时得到了什么:

代码语言:javascript
复制
    package package;

    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.MockitoAnnotations;
    import org.powermock.api.mockito.PowerMockito;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.PowerMockRunner;
    import static org.powermock.api.mockito.PowerMockito.doReturn;

    @RunWith(PowerMockRunner.class)
    @PrepareForTest(ClassA.class)
    public class MyTest {

        @InjectMocks
        private ClassA classA;
        @Mock
        private InputA inputA;
        @Mock
        private InputB inputB;
        @Mock
        private InputC inputC;
        @Mock
        private InputD inputD;

        @Before
        public void setUp() throws Exception {
            MockitoAnnotations.initMocks(this);
            classA = new classA( inputA,  inputB,inputC,  inputD);
        }

        @Test
        public void processPrivateMethod() throws Exception{
            defaultHeader = Aux.createDefaultHeader();

            //create the spy of my ClassA
            classA spy = PowerMockito.spy(classA);
            // Define what I want the method 'generateHeaderForServiceCall' returns when called
            doReturn(defaultHeader).when(spy, "generateHeaderForServiceCall", inputA,defaultHeader,inputF,inputJ,inputK);

            // I try to call the method 'method_i_want_to_test' with classA variable @Injected and with spy of ClassA
            //classA.method_i_want_to_test(defaultHeader,inputNumber);
            spy.method_i_want_to_test(defaultHeader,inputNumber);

        }
    }

1-当我在debug方法中运行这个processPrivateMethod测试时,当调用generateHeaderForServiceCall时,它尝试执行该方法的逻辑并失败,因为标头是一个基本的逻辑。但是,我想要做的是模拟这一点,只返回没有逻辑的默认标头。

2-如果我将generateHeaderForServiceCall更改为受保护,就像某些ClassB方法一样,并为此使用mockito:

代码语言:javascript
复制
    @Test
        public void processProtectedMethod() throws Exception{
            defaultHeader = JUnitTestUtil.createDefaultHeader();
            when(classA.generateHeaderForServiceCall(inputA,defaultHeader,"ccccccc","dxdx",5464564)).thenReturn(defaultHeader);

            classA.method_i_want_to_test(defaultHeader,inputNumber);

        }

但是它返回一个错误,因为该方法是受保护的(如果它是私有的,并且我使用mockito),同样的错误。

错误:generateHeaderForServiceCall(.)保护包中的访问权限。

尝试:

代码语言:javascript
复制
@Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        // Partial mock to mock methods in parent class
        child = new ClasseA(...){
            @Override
            protected Header generateHeaderForServiceCall(...) throws ServiceException {
                //mock logic here
                return aux.createDefaultHeader();;
            }
        };
    }

    @Test
    public void processPrivateMethod() throws Exception{
        defaultHeader = aux.createDefaultHeader();


        //when
        Dossier bdoo = child.method_i_want_to_test(...);

    } 

2-

代码语言:javascript
复制
@Test
    public void processPrivateMethod() throws Exception{
        defaultHeader = JUnitTestUtil.createDefaultHeader();

        child = PowerMockito.spy(new ClasseA(...));


       PowerMockito.doReturn(defaultHeader).when(child, "generateHeaderForServiceCall", context,defaultHeader,"ccccccc","dxdx",5464564);

        //when
        Dossier bdoo = child.method_i_want_to_test(...);
    }

3-

代码语言:javascript
复制
@Test
    public void processPrivateMethod() throws Exception{
        defaultHeader = JUnitTestUtil.createDefaultHeader();

        child = PowerMockito.spy(new ClassA(...));

        father = PowerMockito.spy(new ClasseB());

        PowerMockito.doReturn(defaultHeader).when(father, "generateHeaderForServiceCall", context,defaultHeader,"ccccccc","dxdx",5464564);

        //when
        Dossier bdoo = child.method_i_want_to_test(...);
    }

没人做我想做的事。所有这些都在classB中进入classB方法,并尝试在其中执行逻辑。谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-10-25 21:05:08

听起来你在找spy

,那么,我能和莫基托一起做吗?我需要使用PowerMock吗?

如果它是私有的,那么您需要使用PowerMockito,如果只有其受保护的Mockito能够处理它。

我可以用莫基托和PowerMockito一起使用吗?

PowerMockito是建立在Mockito之上的,所以是的。

注意,应该谨慎地使用spy,例如用于测试遗留代码。通常的建议是重构您的代码。

@PrepareForTest注释需要包括字节码被修改的class --在本例中是Class A

PowerMockito JUnit4**:**对专用方法进行仿真

这里有一个使用String返回而不是Header的简化示例

代码语言:javascript
复制
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Spy;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest(Test.A.class)
public class Test {

    static class A extends B {
        public String process() {
            return "y" + method_i_want_to_test();
        }
    }

    static class B {
        private String generateHeaderForServiceCall() {
            return "abc";
        }

        protected String method_i_want_to_test() {
            return "x" + generateHeaderForServiceCall();
        }
    }

    @Spy
    A classUnderTest = new A();

    @Test
    public void testCustomExceptionIsThrown() throws Exception {

        PowerMockito.doReturn("123").when(classUnderTest, "generateHeaderForServiceCall");
        Assert.assertEquals("yx123", classUnderTest.process());
    }
}

Mockito JUnit5**:**对保护方法进行仿真

代码语言:javascript
复制
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.jupiter.MockitoExtension;

@ExtendWith(MockitoExtension.class)
public class Test {

    static class A extends B {
        public String test() {
            return generateHeaderForServiceCall();
        }
    }

    static class B {
        protected String generateHeaderForServiceCall() {
            return "abc";
        }
    }

    @Spy
    A classUnderTest;

    @Test
    public void testCustomExceptionIsThrown() throws Exception {

        Mockito.when(classUnderTest.generateHeaderForServiceCall()).thenReturn("123");
        Assertions.assertEquals("123", classUnderTest.test());
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58561739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档