【问题标题】:Testing method which calls protected method form another class从另一个类调用受保护方法的测试方法
【发布时间】:2018-12-14 12:09:18
【问题描述】:
class A {
    protected obj init()
}

class B {
    public void testingThis() {
      //..stuff
      obj = a.init()
      moreStuff(obj)
    }
}

我正在测试班级B。我这样做有困难,因为它使用类A 的方法来获取对象。我该如何解决这个问题?

附:不能改变可见性,不能放在同一个包里。

【问题讨论】:

  • 你要么可以访问a,在这种情况下你可以模拟它。否则你甚至不应该费心去了解测试这个实现细节

标签: testing reflection junit mockito


【解决方案1】:

有了这样的限制,“最简单的”就是在测试类或其子类A 的包中声明一个类,这是您要模拟的依赖项。
存根init() 返回夹具数据,应该没问题。
您可以在存根类的构造函数中传递它。

这将提供这个存根类,您可以将其用作测试类中的依赖项:

class StubA extends A {

    Foo stubbedFoo;
    public StubA(Foo stubbedFoo){this.stubbedFoo=stubbedFoo}

    @Override
    public Foo init(){
       return stubbedFoo;
   }
}

测试样本:

class BTest {

    @Test
    public void doThat() {
      StubA a = new StubA(anyFooValue);
      B b = new B(a);
      // action
      b.doThat();
    }
}

【讨论】:

  • 我该怎么做 B b = new B(a);这个没有构造函数?
  • 如果你没有构造函数,也没有设置依赖的setter,你想怎么设置?
【解决方案2】:

我认为 B 的写法不正确。对 A 的引用应该是注入的依赖项。现在你有 2 种方法来测试它:干净的方式或 PowerMock 方式。如果您采用干净的方式,您将重构 B,使其具有注入到 A 的依赖项,因此您可以使用模拟控制 A 类。

class B {
    A myAclass;

    @Inject
    public B(A myAclass) {
        this.myAclass=myAclass;
    }

    public void testingThis() {
      //..stuff
      obj = myAclass.init()
      moreStuff(obj)
    }
}

现在的测试看起来像这样:

@RunWith(MockitoJUnitRunner.class)
public class Btest {
    @Mock
    A myAmock; 

    @InjectMocks
    B sut; // System-Under-Test

    @Test
    public void testB() {
        X theObject = mock(X.class);
        when(myAmock.init()).thenReturn(theObject);

        // call the method
        sut.testingThis();

        //verify the call being done
        verify(a, times(1)).init();
    }
}

如果您无法更改 B 的代码,您仍然可以对其进行测试,但您需要 PowerMock(ito)。

@RunWith(PowerMockRunner.class)
@PrepareForTests({A.class, B.class})
public class Btest {
    B sut;

    @Test
    public void testB() {
       A aMock = mock(A.class);
       X thObject = mock(X.class);

       // I can't determine from the code if the init method is static or you use an instance. In case of an instance you must override the constructor:
       PowerMockito.mockStatic(A.class);
       PowerMockito.whenNew(A.class).withNoArguments().thenReturn(aMock);
       when(aMock.init()).thenReturn(theObject);

       // In case of a static method you should mock that method
       when(A.init()).thenReturn(theObject);

       // Now construct B to test it.
       sut = new B();
       sut.testingThis();

       // verify
       verify(aMock, times(1)).init();
    }
}

【讨论】:

    猜你喜欢
    • 2020-08-02
    • 2013-02-04
    • 2021-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多