我有两个枚举:
public enum X {
INSTANCE;
private final Y y = Y.INSTANCE;
public boolean isfunc() {
return y.someMethod();
}
}
public enum Y {
INSTANCE;
public boolean someMethod() {
return true;
}
}
我已经通过使用Whitebox进行模拟为Y
编写了一个单元测试类。但是,在为X
编写单元测试用例时,需要获得以下异常:
我收到以下错误消息:
Cannot mock/spy class
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types
这是单元测试用例:
public class XTest {
@Mock private Y yMock;
@Before
public void setUp() throws Exception {
Whitebox.setInternalState(Y.INSTANCE, "y", yMock);
}
我知道这个问题是因为我试图模拟一个枚举,它是一种原始类型。我想找到解决方法。
答案 0 :(得分:1)
以下是Mockito文档中的内容:
39。模拟最终类型,枚举和最终方法(自2.1.0开始)
Mockito现在提供了一个孵化,可选的模拟最终课程支持 和方法。这是一个了不起的改进,证明了 Mockito对改善测试体验的永恒追求。我们的 我们的目标是使Mockito与最终的类和方法“兼容”。 以前,它们被认为是不可模仿的,从而阻止了用户 嘲笑。我们已经开始讨论如何制作此功能 默认情况下启用。目前,该功能仍是可选功能,因为我们 等待社区的更多反馈。
此功能默认情况下处于关闭状态,因为它基于 完全不同的模拟机制,需要更多反馈 来自社区。 p>
但是,我宁愿建议用单例类中的静态成员单例替换枚举单例,因为如本测试用例所示,它通常被认为更具可读性,同等的线程安全性和可配置性。
类似这样的东西:
public class Y {
private Y() {}
private final static Y y = new Y();
public static Y getInstance() {
return y;
}
public boolean someMethod() {
return true;
}
}
enum X {
INSTANCE;
private final Y y = Y.getInstance();
public boolean isfunc() {
return y.someMethod();
}
}
public class XTest {
@Mock private Y yMock;
@Before
public void setUp() throws Exception {
Whitebox.setInternalState(X.INSTANCE, "y", yMock);
}
@Test
void test() { // ...
}
}
我还要补充一点,我不喜欢在测试期间使用Whitebox。我相信测试可以做的任何事情,我的代码都应该可以做,因为测试是模块的第一个真正的客户,并且可以指示将来的客户可能想要做什么。例如,就像测试想用模拟Y替换Y一样,将来有人可能会想将X与其他生产Y一起使用。
我将更改Y以使用一个接口,并删除X中y变量的最后一个,以便使其可设置,如下所示:
interface IY
{
public boolean someMethod();
}
public class Y implements IY {
private Y() {}
private final static IY y = new Y();
public static IY getInstance() {
return y;
}
public boolean someMethod() {
return true;
}
}
enum X {
INSTANCE;
private IY y = Y.getInstance();
public void setY(IY y)
{
this.y = y;
}
public boolean isfunc() {
return y.someMethod();
}
}
public class XTest {
@Mock private Y yMock;
@Before
public void setUp() throws Exception {
X.INSTANCE.setY(yMock);
}
@Test
void test() { // ...
}
}
我会牺牲一些安全性(例如X.INSTANCE.setY(null);的可能性)以实现可配置性和简洁的代码。