【问题标题】:How to mock generic method using mockito?如何使用 mockito 模拟泛型方法?
【发布时间】:2019-04-10 06:16:06
【问题描述】:

无论我尝试什么,我都在尝试模拟一个泛型方法但得到类强制转换异常。正在测试的类是

public class TClass {
    private byte[] data;
    public <T extends SInterface> T asObject(T item){
        item.SMethod(this.getData());
        return item;
    }

    private byte[] getData() {
        return data;
    }
}

测试类

@RunWith(MockitoJUnitRunner.class)
public class TClassTest {
    @Mock
    SSInterface sClass;
    @Mock
    SObject sObject;

    TClass tClass = new TClass();


    @org.junit.Before
    public void setUp() throws Exception {
    }

    @org.junit.Test
    public void asObject() {
        Mockito.when(tClass.asObject(new SSClass())).thenReturn(sClass);
    }
}

其他帮助类接口是:

 public interface SInterface {
    public void SMethod(byte[] in);
}



public interface SSInterface extends SInterface {
}


public class SSClass implements SSInterface {
    @Override
    public void SMethod(byte[] in) {
    }
}

public class SObject {
}

我得到的错误是:

无法解析方法 thenReturn(generic.SSInterface)

如果我使用Mockito.when(tClass.asObject(new SSClass())).thenReturn(new SSClass());

我明白了 org.mockito.exceptions.misusing.MissingMethodInvocationException: when() 需要一个参数,该参数必须是“模拟方法调用”。 例如: when(mock.getArticles()).thenReturn(articles);

此外,出现此错误的原因可能是: 1.你存根:final/private/equals()/hashCode()方法。 这些方法不能被存根/验证。 不支持在非公共父类上声明的模拟方法。 2. 在 when() 中,你不会在 mock 上调用方法,而是在其他对象上调用。

at generic.TClassTest.asObject(TClassTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:78)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:84)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:161)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

【问题讨论】:

    标签: java junit mockito


    【解决方案1】:

    你有不兼容的类型,它与 mockito 无关。 asObject() 返回与其接收相同的类型,并且它必须是 SInterface 类型。

    根据您要达到的目标,您可以返回 SSClasss 的实例:

    Mockito.when(tClass.asObject(new SSClass())).thenReturn( new SSClass());
    

    或者你可以让TClass扩展SInterface然后:

    Mockito.when(tClass.asObject(tClass)).thenReturn(tClass);

    【讨论】:

    • Mockito.when(tClass.asObject(new SSClass())).thenReturn(new SSClass()); 不起作用
    • Bcs tClasss 不是模拟。添加@Mock TClass tClass; 使其工作。但话又说回来,不清楚您要达到什么目的。
    【解决方案2】:

    我认为你想测试 TClass.asObject() 但验证 sClass.SMethod() 被调用。

    @org.junit.Test
    public void asObject() {
            final SSInterface sut = new SSClass();
    
            final SSInterface returned = sut.asObject(sClass);
    
            assertEquals(sClass, returned);
            Mockito.verify(sClass).SMethod(any());    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-08
      • 2020-03-20
      • 2011-01-17
      相关资源
      最近更新 更多