问题简单描述
FordAmbientLightManager 类中setAmbL_ALM_Set()函数,函数中进行了new AmbientLightSettingReq()的操作。
也就是:测试类的函数中构造了局部的对象,无法直接获取到该局部对象,Mockito从3.5.0版本开始支持模拟构造函数,通过Mockito.mockConstruction()接口实现。
具体情况
- 被测试类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);
}
//该函数内部构造了局部对象,在测试时无法直接获得这个对象
public void setAmbL_ALM_Set(int ambL_ALM_Set) {
AmbientLightSettingReq ambientLightSettingReq = new AmbientLightSettingReq();
ambientLightSettingReq.setAmbL_ALM_Set(ambL_ALM_Set);
Log.d(TAG, "setAmbL_ALM_Set:ambientLightSettingReq= " + ambientLightSettingReq.toString());
sendRequestNoRsp(ambientLightSettingReq);
}
}
- 问题具体分析
测试类的函数中构造了局部的对象,无法直接获取到该局部对象,Mockito从3.5.0版本开始支持模拟构造函数,通过Mockito.mockConstruction()接口实现。 - 具体测试代码
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);
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);
}
Class c = fordAmbientLightManager.getClass();
Field manager = c.getDeclaredField("manager");
manager.setAccessible(true);
manager.set(fordAmbientLightManager, null);
}
@Test
public void testSetAmbL_IP_Color_Value() throws NoSuchFieldException, IllegalAccessException {
//prepare
//进行construct处理,可以理解为一个列表吧,里面都是我们想得到的mock的对象
MockedConstruction<AmbientLightSettingReq> AmbientLightSettingReq = Mockito.mockConstruction(AmbientLightSettingReq.class);
//invoke
fordAmbientLightManager.setAmbL_IP_Color_Value(1);
//verify
//因为consruct后得到的A...Req类似列表,所以get(0)得到的就是我们想要的mock的局部变量,对此mock的局部变量再执行断言
Mockito.verify(AmbientLightSettingReq.constructed().get(0)).setAmbL_IP_Color_Value(1);
//construct使用结束后一定要记得关闭,否则会报错
AmbientLightSettingReq.close();
}
}
存在问题
- 只是知道遇到局部变量需要使用construct对应的语法,处理流程也会,但是不是很了解其中的原理,其实讲解过当时听明白了但是现在给忘记了 T T
技术细节
1.CONSTRUCT
技术代码
(有空手敲下,,,)
小结
1.局部对象的处理,要用到construct