[英]Mocking superclass method call using mockito is not working
我一直在嘗試從子類覆蓋的方法中對超類方法調用存根,但直到現在我都沒有任何成功的運氣。 我也廣泛搜索了谷歌和 SO 問題。
這是我正在使用的測試代碼。 問題是,就我而言,超類和子類方法都被存根了。
@Test(enabled = true)
public void superclassMockTest() throws Exception {
ChildClass adc = getChildClass ();
doReturn(getReturnObject())
.when((SuperClass) adc).getObject(any(String.class), any(String.class), any(Map.class))
ResultObject result= adc.getObject("acc", "abc", null);
assertNotNull(result);
assertNotNull(result.getPropertyValue("attribute"));
}
該屬性在Subclass's getObject(...) method
中的ResultObject
上設置。 我想存根super.getObject(...) call within the subclass's to return some arbitrary object
由getReturnObject() method
提供的一些任意 object 。
正在發生的問題是:即使調用ResultObject result= adc.getObject("acc", "abc", null);
正在被存根並且屬性未設置,這導致了問題。
我什至嘗試添加: doCallRealMethod().when(adc).getObject(any(String.class), any(String.class), any(Map.class));
就在實例上的實際調用之前,希望實例上的實際方法被調用。 但在這種情況下, super.getObject(...) 不會被存根並被執行。
這是我陷入困境的一種非此即彼的情況,我可以同時存根或不能存根。 請幫忙!
此演員表不會產生您正在嘗試的效果:
((SuperClass) adc).getObject("", "", null)
調用的 getObject 方法是 adc 實例之一,與強制轉換無關。 演員表只是編譯時的糖。
您需要更改設計,例如使用不同的方法名稱或組合來代替 inheritance。 其他可能性是在測試運行時覆蓋超類,將修改后的版本復制到具有與原始 package 相同的測試源:
像這樣:
src/main/java
\-------- com.xyz.pac
\--------- SuperClass.java
\--------- ChildClass.java
src/test/java
\-------- com.xyz.pac
\--------- SuperClass.java
\-------- test.com.xyz
\--------- MyTest.java
這只會影響您的測試。 測試包在運行時不可用。
有幾個選項
Parent
和Child
中不同super
的調用移動到Child
class 上的private
方法中Parent
級public class A {
public String getName() {
return "BOB";
}
}
public class B {
private final A a;
public B(A a) {
this.a = a;
}
public String getName() {
String name = a.getName();
return name;
}
}
class BTest {
@Test
void shouldMockA() {
A a = mock(A.class);
when(a.getName()).thenReturn("JANE");
assertThat(a.getName(), is("JANE"));
}
}
**此示例使用 JUnit 請按照此鏈接設置 TestNG **
public class Parent {
public String getName() {
return "BOB";
}
}
public class Child extends Parent {
public String getNameChild() {
String name = super.getName();
return name;
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest(Parent.class)
public class ChildTest {
private final Child child = PowerMockito.spy(new Child());
@Test
public void shouldMockParentSuperCall() {
PowerMockito.doReturn("JANE").when(child).getName();
assertThat(child.getNameChild(), is("JANE"));
}
}
** 此示例使用 JUnit 請按照此鏈接設置 TestNG **
public class Child extends Parent {
public String getName() {
String name = callParentGetName();
return name;
}
private String callParentGetName() {
return super.getName();
}
}
@RunWith(PowerMockRunner.class)
@PrepareForTest({Child.class, Parent.class})
public class ChildTest {
private final Child child = PowerMockito.spy(new Child());;
@Test
public void shouldMockParentSuperCallName() throws Exception {
PowerMockito.doReturn("JANE").when(child, "callParentGetName");
assertThat(child.getName(), is("JANE"));
}
}
** 不建議這樣做(查看 Java 代理、Instrumentation ByteBuddy 等)**
public class Parent {
public String getName() {
return "BOB";
}
}
public class Child extends Parent {
public String getName() {
String name = super.getName();
return name;
}
}
class ChildTest {
@Test
void shouldChangeParentMethod() {
ByteBuddyAgent.install();
new ByteBuddy()
.redefine(Parent.class)
.method(named("getName"))
.intercept(FixedValue.value("JANE"))
.make()
.load(
Parent.class.getClassLoader(),
ClassReloadingStrategy.fromInstalledAgent());
Child child = new Child();
assertThat(child.getName(), is("JANE"));
// Remove anything added e.g. class transformers
}
}
您應該能夠更改嘗試強制轉換的代碼:
adc.super.getObject();
正如我在上面的評論中所說,根據文檔,Java 中的 super 關鍵字是一個引用變量,它提供對對象父級的引用。 如果演員陣容確實是問題所在,則此更改應該可以解決問題。
這是個有趣的問題。 當您使用 inheritance 時,即使您在測試用例中模擬父 class,在子的自動裝配期間,它始終指的是實際的父 class,而不是模擬的那個。 這與 Mock 框架有關。 似乎它缺少允許在子實例化期間模擬父類的能力
@Component("parent")
public class Parent{
public String getMsg(){
return "Parent";
}
}
@Component
@Lazy
public class Child {
@Autowired
Parent parent;
public String getMsg(){
return "Child" + parent.getMsg();
}
}
The test case -
@MockBean
@Qualifier("parent")
Parent base;
@BeforeEach
public void initMockedBean(){
when(base.getMsg()).thenReturn("Dummy"); }
您可以嘗試在 Mockito 上提出問題。 也許他們會將其添加到功能中
在回答這個問題時,我發現這個線程證實了我的回答 - Mockito How to mock only the call of a method of the superclass還有一個建議。 你可以試試看是否對你有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.