【问题标题】:Mock static default interface method模拟静态默认接口方法
【发布时间】:2017-06-22 13:14:05
【问题描述】:

我需要为以下情况创建一个单元测试:

被测类:

class MyProducer {

private Producer producer = null;
private ProducerCreator producerCreator = null;

public MyProducer() {
 producerCreator = ProducerCreator.create(string name);
 producer = producerCreator.createProducer();

}
public boolean foo() {
  return producer.foo();
}
}

ProducerCreator 类来自外部包,没有源代码:

public interface ProducerCreator {

static default ProducerCreator create(String name) {
  return new ProducerCreatorImpl(...)
  }
 }

所以我试图用 PowerMockito 模拟静态调用:

@RunWith(PowerMockRunner.class)
@PrepareForTest(ProducerCreator.class)
public class ProducerTest {

    @Test
    public void fooTest() {


        ProducerCreator producerCreatorMock = Mockito.mock(ProducerCreator.class);

 PowerMockito.mockStatic(ProducerCreator.class); 
 PowerMockito.when(ProducerCreator.class, "createProducer", "name").thenReturn(producerCreatorMock);

(也试过这个:

PowerMockito.when(ProducerCreator.create("name")).thenReturn(producerCreatorMock);

但它没有做任何改变)

        MyProducer myProducer = new MyProducer();


    assertTrue(myProducer.foo());



}

通常我会得到以下内容:

org.mockito.exceptions.misusing.UnfinishedStubbingException: 
...
E.g. thenReturn() may be missing.
Examples of correct stubbing:
    when(mock.isOk()).thenReturn(true);
    when(mock.isOk()).thenThrow(exception);
    doThrow(exception).when(mock).someVoidMethod();
Hints:
 1. missing thenReturn()
 2. you are trying to stub a final method, you naughty developer!
 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed

或任何其他错误或不需要的行为,而不是适当的模拟。 问题是由于界面中的“静态默认”方法引起的吗? 在互联网上没有找到此类案例的任何示例。

更新: 我不能分享真正的代码,因为它是专有的。

有一个来自外部包的真正静态默认方法可以编译:

public interface ProducerCreator extends Closeable {
    static default ProducerCreator create(String serviceUrl) throws ProducerCreatorException {
        return ...
    }

UPD 2:该包是一个 JNI 包 - 从 CPP 代码生成..

【问题讨论】:

  • 你确定该方法既是默认方法又是静态方法。这种组合会导致编译错误。
  • 当然,当然。我看到了代码:)
  • 您不能同时拥有staticdefault 的接口方法。 “确定,确定”告诉我们您没有尝试编译您的代码示例,也没有进行尽职调查。 “我看到代码”是什么意思?该响应使您的问题无效。 docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.4 "如果使用多个修饰符 abstractdefaultstatic 声明方法,则会出现编译时错误。"请向我们展示您的真实代码。您显示的内容无法编译。
  • 原来是C++代码生成的JNI包
  • @MaciejKowalski 那么你现在能说什么呢?

标签: java junit mockito powermock powermockito


【解决方案1】:

您的代码无法编译。我做了一些假设:

public class Producer {
    public boolean foo(){
        return true;
    }
}

public interface ProducerCreator {
    public static ProducerCreator create(String name) {
        return new ProducerCreatorImpl(name);
    }

    Producer  createProducer();
}

public class MyProducer {

    private Producer producer = null;
    private ProducerCreator producerCreator = null;

    public MyProducer() {
        producerCreator = create("name");
        producer = producerCreator.createProducer();

    }
    public boolean foo() {
        return producer.foo();
    }
}
public class ProducerCreatorImpl implements ProducerCreator{


    public ProducerCreatorImpl(String name) {

    }

    @Override
    public Producer createProducer() {
        return new Producer();
    }
}

你的测试对我有用:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ ProducerCreator.class })
public class DatasourceTest {

    @Test
    public void fooTest() {


        ProducerCreator producerCreatorMock = Mockito.mock(ProducerCreator.class);

        PowerMockito.mockStatic(ProducerCreator.class);
        PowerMockito.when(ProducerCreator.create(Mockito.anyString())).thenReturn(producerCreatorMock);

        Producer prodMock = Mockito.mock(Producer.class);
        Mockito.when(producerCreatorMock.createProducer()).thenReturn(prodMock);
        Mockito.when(prodMock.foo()).thenReturn(false);

        MyProducer myProducer = new MyProducer();
        boolean result = myProducer.foo();

        Assert.assertFalse(result);

        Mockito.verify(prodMock).foo();

    }
}

【讨论】:

  • 我放在这里的代码是我无法发布的真实代码的抽象。在您的示例中,接口函数如果是静态的,但不是默认的。如果添加默认关键字,是否有效?
  • 不,正如@Macijej 评论你的问题,它不能编译。这是静态和默认的非法组合。我添加了一些更复杂的测试,它实际上测试了一些东西
  • JNI 呢?
  • 阅读更新。静态默认值来自 JNI 包。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 2021-06-02
  • 1970-01-01
  • 1970-01-01
  • 2015-07-11
  • 2015-05-07
相关资源
最近更新 更多