由于某种无法解释的原因,我在构造函数中分配的字段(currentExp
)在为我的单元测试使用模拟时未正确设置。我通过使用我的Storage
类(使用 SharedPreferences)通过 loadExperience
方法加载字段来分配字段currentExp
。当我对此进行单元测试时,我想模拟Storage
类,因此loadexperience
返回值 10。
这是我的具体Experience
课:
public class Experience extends StorageObject {
private int currentExp = 0;
public Experience() {
this(new Storage());
}
@VisibleForTesting
protected Experience(Storage storage) {
super(storage);
} // Debug point #2
@Override
protected void init(Storage storage) {
this.currentExp = storage.loadExperience();
} // Debug point #1
}
它扩展了StorageObject
:
public abstract class StorageObject {
protected Storage storage;
protected StorageObject() {
this(new Storage());
}
@VisibleForTesting
protected StorageObject(Storage storage) {
this.storage = storage;
init(storage);
}
protected abstract void init(Storage storage);
}
这是我的单元测试:
@Test
public void testConstructor_StorageValuePositive_IsSetAsCurrentExp() {
int expectedSavedExp = 10;
Storage storageMock = mock(Storage.class);
doReturn(expectedSavedExp).when(storageMock).loadExperience();
Experience exp = new Experience(storageMock);
assertEquals(expectedSavedExp, exp.getCurrentExp());
}
在调试时,我发现模拟确实有效,并且值 10 在调试点 #1 分配给currentExp
。然后不久之后,在调试点 #2 处,该值似乎再次为 0。
任何人都知道这里发生了什么,以及如何解决这个问题?
这里的问题是初始化顺序。超级构造函数首先发生,然后进行字段初始化。
因此,您的构造函数将超级调用中的currentExp
设置为 10,然后字段以 0 启动。
那你能做什么呢?一些想法:将currentExp
移动到父类或不为其提供默认值。
更多阅读材料:
http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.5
https://stackoverflow.com/a/14806340/5842844