【问题标题】:Mock Protected Parent Method When the Parent is in a Different Package当父级在不同的包中时模拟受保护的父级方法
【发布时间】:2016-01-08 19:10:02
【问题描述】:

我需要在我的测试类的父类中模拟一个受保护的方法,但父类位于不同的包中,因此我的测试类无法访问该方法,因此我无法模拟它。这个问题必须有一个无需重构的解决方案

我需要使用 Powermock 和 Mockito。这是 JAR

  • mockito-all 1.10.8
  • powermock-core 1.6.1
  • powermock-module-junit4 1.6.1
  • powermock-api-mockito 1.6.1
  • junit 4.12

这是遗留代码,所以我无法重构,但这是简化的代码。

Parent.java

package parent;

public class Parent {

    // Want to mock this protected parent method from different package
    protected String foo() {

        String someValue = null;

        // Logic setting someValue

        return someValue;
    }
}

Child.java

package child;

import parent.Parent;

public class Child extends Parent {

    String fooString = null;

    public String boo() {

        this.fooString = this.foo();

        String booString = null;

        // Logic setting booString

        return booString;
    }
}

ChildTest.java

package child;

import static org.mockito.Mockito.spy;

import org.junit.Assert;
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;

import parent.Parent;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Parent.class, Child.class })
public class ChildTest {

    // Class Under Test
    Child cut;

    @Before
    public void setUp() throws Exception {

        // Partial mock to mock methods in parent class
        cut = spy(new Child());

    }

    @Test
    public void testBoo() {

        // TODO: Need to mock cut.foo() but can't figure out how.

        // Following gives me this error: The method foo() from the type Parent is not visible
       Mockito.when(((Parent)cut).foo()).thenReturn("mockValue");

        // Test
        cut.boo();

        // Validations
        Assert.assertEquals(cut.fooString, "mockValue");

    }
}

【问题讨论】:

    标签: java unit-testing mockito powermock powermockito


    【解决方案1】:

    只需创建一个用于测试的新类,扩展您要测试的类,并在那里覆盖您的方法。

    看起来像这样:

    public class ChildForTest extends Child{
         @Override
         protected String foo() {
             //mock logic here
        }
    }
    

    编辑: 如果你想避免新的类定义,你可以使用匿名类

    @Before
    public void setUp() throws Exception {
    
        // Partial mock to mock methods in parent class
        cut = new Child(){
            @Override
            protected String foo(){
                //mock logic here
                return "";
            }
        };
    }
    

    【讨论】:

    • 我不想重构任何 Java。我只想编写一个新的单元测试类并利用 PowerMock 和 Mockito。
    • 你不需要重构任何东西,你只需创建一个新的类来模拟这个 foo 方法,而不是在测试中使用 Child 对象,你可以使用 ChildForTest 对象,因为唯一的区别是成为 foo() 方法的工作方式
    • 但是这是引入了一个新的类。我要做的就是覆盖所有 Child.java 而无需进入 Parent.java。所以我想通过模拟 Parent.java 中的所有内容来覆盖 Child.java 的所有内容。
    • 你可以使用我上面推荐的解决方案来做到这一点。
    • Mocking 框架被高估和过度使用 IMO。您可以在 Bob 叔叔的文章 blog.8thlight.com/uncle-bob/2014/05/10/WhenToMock.html 中阅读相关内容(编写您自己的模拟。部分)
    【解决方案2】:

    您可以使用 PowerMock 来模拟任何公共方法。

    @RunWith(PowerMockRunner.class)
    public class ChildTest {
    
        @Test
        public void testBoo() throws Exception {
            //given
            Child child = PowerMockito.spy(new Child());
            PowerMockito.when(child, "foo").thenReturn("mockValue");
    
            //when
            String boo = child.boo();
    
            //then
            Assert.assertEquals("boo+mockValue", boo);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-09
      • 2018-10-12
      • 2019-10-27
      • 2018-09-15
      相关资源
      最近更新 更多