问题简单描述
被测试类如果是单例模式,在每次test结束后需要格外注意处理
具体情况
- 被测试类Java代码
public class FordAmbientLightManager extends FordCommonManager {
private static final String TAG = "FordAmbientLightManager";
private static FordAmbientLightManager manager;
private AmbientLightSettingRsp ambientLightSettingRsp;
private List<IAmbientLightChange> mIAmbientLightChangeListeners;
//单例模式
public static synchronized FordAmbientLightManager getInstance(Context context) {
if (null == manager) {
manager = new FordAmbientLightManager(context);
}
return manager;
}
//初始化定义函数
public FordAmbientLightManager(Context context) {
super(context, APPID_ID_1021);
mIAmbientLightChangeListeners = new ArrayList<>();
addIResponseCallbackListener(mCallback);
addISynchronizationInterfaceListener(mISynchronizationInterface);
}
}
- 问题具体分析
因为是单例模式,所以如果测试的时候不在每一次test结束之后都对test函数中对原Java类中值作出的改变清空,会影响所有测试用例,即需要在afterEach中对具体进行处理 - 具体测试代码
class FordAmbientLightManagerUT extends BaseUnitTest {
private FordAmbientLightManager fordAmbientLightManager;
private Context context;
private AutoCloseable closeable;
@BeforeAll
public static void beforeAll() {
mockStatic(Log.class);
mockStatic(Car.class);
}
@BeforeEach
public void beforeEach() {
closeable = MockitoAnnotations.openMocks(this);
Context context = Mockito.mock(Context.class);
//对得到的mock对象进行插桩(也就是模拟其行为)以便后续使用
Mockito.when(context.getApplicationContext()).thenReturn(context);
fordAmbientLightManager = FordAmbientLightManager.getInstance(context);
}
@AfterEach
public void afterEach() throws IllegalAccessException, NoSuchFieldException {
try {
closeable.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
//在每个test结束后都对单例进行一次初始化
Class c = fordAmbientLightManager.getClass();
Field manager = c.getDeclaredField("manager");
manager.setAccessible(true);
manager.set(fordAmbientLightManager, null);
}
}
存在问题
- 无
技术细节
- 单例模式在afterEach里处理单例
- mock插桩的使用
小结
- 一开始没有考虑到是单例模式,所有测试函数写完之后一运行只有第一个过了后面全红,很崩溃,后来发现是单例模式,在每个test结束之后都要重新处理一下,体现在代码里就是在afterEach函数中对单例进行清空,这是Junit5的特性决定的,在每次test结束后都会执行一次afterEach,此时不能使用afterall,afterAll是在所有都结束之后才执行,一般和beforeAll成对出现,并且一般都是处理静态相关。