Mockito - 如何忽略私有成员对象的方法调用?

时间:2014-09-17 17:19:24

标签: java mockito powermock

我想测试此方法,但在方法内部创建一个新对象,然后调用该新对象的方法。我想跳过它(它涉及登录到我不感兴趣的j2ee服务器数据库)。作为一个简单的例子,我只想验证param1.logic()被调用一次,但测试最终失败,因为obj尝试使用我不想打扰输入的凭据登录。私有Object2 obj变量没有getter或setter,但有没有办法跳过构造函数并跟随logon调用?

public class Object1{

    private Object2 obj;

    public void method(Object3 param1, String param2){
        //functionality
        //logic to be tested
        param1.logic();
        //end functionality

        //how can I skip these two lines?
        obj = new Object2(param1);
        obj.logon(param2,param2,null, false);
    }
}      

这是我尝试使用的内容,但仍在调用obj.logon中的方法。

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;            

@RunWith(PowerMockRunner.class)
@PrepareForTest(Object2.class)
public class TestObject
{
    @SuppressWarnings("unchecked")
    @Before
    public void init() throws Exception
    {
        var1 = mock(Object3.class)
        obj2 = mock(Object2.class);
        PowerMockito.whenNew(Object2.class).withAnyArguments().thenReturn(obj2);
    }

    @Test
    public void testInvokeStandAloneJob() throws Exception
    {        
        TestObject test = spy(new TestObject());
        Mockito.doAnswer( new Answer<Object>(){
            public Object answer(InvocationOnMock invocation){
                Object[] args = invocation.getArguments();
                return "called with arguments: " + args;
            }
        }).when(obj2).logon(Mockito.anyString(), Mockito.anyString(),Mockito.anyString(), Mockito.anyBoolean());
        //also tried doNothing
        //Mockito.doNothing().when(obj2).logon(sDomainName, username,null, false);  

        //call method                  
        test.method(var1, var2);

        verify(var1,times(1)).logic();
    }

如何制作这两行(构造函数和以下方法什么都不做?)

2 个答案:

答案 0 :(得分:1)

我相信你可以使用powermock来模拟对new()的调用,并返回一个模拟对象,该对象在调用logon方法时什么都不做。

在使用PowerMock之前,请务必按照此页面上的说明操作:https://code.google.com/p/powermock/wiki/MockConstructor

具体做法是:

确保将其添加到测试类的顶部

@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassThatCreatesTheNewInstance.class)
  

使用PowerMock.createMock(NewInstanceClass.class)创建应该构造的类的模拟对象(让我们称之为mockObject)。

或者,您可以重新设计您的课程,以便在该方法中不使用new关键字。 (无论如何都是不好的做法)

答案 1 :(得分:0)

如果严格遵循依赖注入模式,模拟是测试的好方法。如果你不这样做,嘲笑就没那么大了。

您的行

obj = new Object2(param1);

违反了依赖注入。

您需要将其替换为

obj = object2Factory.create()

然后在构造函数中注入object2Factory或作为属性。

<强>更新

虽然我仍然不知道如何模拟原始代码,但我想制作另一种重构方法。

你可以重构行

    obj = new Object2(param1);
    obj.logon(param2,param2,null, false);

进入他们自己的package-private方法:

Object2 createObject2(Object3 param1, String param2) {
        Object2 o = new Object2(param1);
        o.logon(param2,param2,null, false);
        return o;
}

然后,您可以使用spy()来模拟createObject2()。