1

我正在尝试测试一个类(使用 Jukito 和 Mockito),不幸的是它扩展了另一个具有静态方法调用的类。是否有可能以某种方式跳过这个电话?我宁愿不使用 PowerMockito。

public class A extends B {

    @Inject
    public A(final String s){
        super(s);
    }
}

public abstract class B {

    private String s;

    protected String m = C.get().createUniqueId(); //Exception is thrown here

    public B(String s){
        this.s = s;
    }
}

public class C {
    private static C c; //assume this is never null

    public static C get() {
        return c;
    }   

    public final native String createUniqueId() {}

}

@RunWith(JukitoRunner.class)
public class ATest {

    @Inject 
    A a;

    @Test
    public void onMethod1Test(){
    }
}

运行 ATest 时,出现以下错误:

Error injecting constructor, java.lang.UnsatisfiedLinkError: C

我认为这是因为静态方法,我错了吗?

请注意,所有课程都只是我真实课程中的示例,C 课程不是我编写的,无法更改(不幸的是)。但是我的课程背后的想法和这些是一样的,我只是改了名字,只留下了相关的部分。

4

2 回答 2

1

Jukito声称

JUnit、Guice 和 Mockito 的综合力量。

但问题是:这些产品都不允许您模拟静态方法。

唯一能够做到这一点的框架:PowerMock(ito) 和 JMockit。

正如您已经解释的那样:通常您可以通过简单地编写可测试的代码(避免静态调用)来“绕过”这个“缺陷” 。但是由于您无法改进您的设计,您只有这两个选择:使用 PowerMock(ito) 来测试这个类 - 或者不测试它。

于 2017-07-28T08:43:49.120 回答
0

所以目标是用于在任何新实例上C生成. 你无法控制,你试图弄清楚如何测试它,对吧?我认为您必须选择毒药,但我可以根据您的情况考虑另一种“毒药”选择。mBC

您添加一个静态字段B并为其提供更多访问权限,否则将是合适的:

public abstract class B {
   static C c = C.get();
   private String s;
   protected String m = c.createUniqueId();
   public B(String s){
     this.s = s;
   }
}

现在您可以B.c在测试中重新分配给模拟实例。我对 JUnit 和 Spock 更熟悉,所以我会尝试让您弄清楚其中的机制。由于单元测试与它们正在测试的类位于同一个包中,因此您可以使用包私有范围。如果A与 位于不同的包中B,则必须将其提升为protected. 这既快速又简单,但让您有可能重新分配其他代码B.c。您必须根据根本不测试的风险来判断这种风险A

您还可以考虑添加类和接口以完全隐藏C。本质上,您创建的东西必须生成. 在单元测试中模拟供应商,在生产中使用基于. 我能想到的每一种方法都是混乱的,或者不会强制每个子类以相同的方式生成。唯一的例外是如果使用组合并放置on的实例实际上更有意义。那么你可能有一个体面的方法来做到这一点。ABBFactorySupplier<String>mCBmBA

于 2017-07-28T20:31:33.677 回答