[使用PowerMock的android中的单元测试单例类方法

问题描述 投票:0回答:1

我需要对内部使用RxJava Singles的Singleton类的方法进行单元测试,并使用PowerMock测试框架模拟静态类和方法。我尝试了各种方法来模拟Schedulers.io()和AndroidSchedulers.mainThread()方法,但无法正常工作。我在UserApi.verifyUserData()方法内的第。subscribeOn(Schedulers.io())行出现了[[java.lang.NullPointerException错误。

Singleton类UserApi(正在测试的类)

final public class UserApi { private CompositeDisposable compositeDisposable; private String userID = UUID.randomUUID().toString(); private final Handler handler; //private final SchedulerProvider schedulerProvider; private UserApi() { super(); this.handler = new Handler(); //this.schedulerProvider = schedulerProvider; } public static UserApi getInstance() { return SingletonHolder.sINSTANCE; } private static final class SingletonHolder { private static final UserApi sINSTANCE; static { sINSTANCE = new UserApi(); } } // Rest Api call public void verifyUserData(byte[] doc, byte[] img) { this.compositeDisposable = new CompositeDisposable(); String docStr = Base64.encodeToString(doc, Base64.NO_WRAP); String imgStr = Base64.encodeToString(img, Base64.NO_WRAP); final Disposable apiDisposable = IdvManager.getInstance().getUserManager().verifyUserData(docStr, imgStr) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<JsonObject>() { @Override public void accept(JsonObject verifyResponse) throws Exception { pollResult(); } }, new Consumer<Throwable>() { @Override public void accept(Throwable error) throws Exception { // handle error code... } }); this.compositeDisposable.add(apiDisposable); } private void getVerificationResult() { // code here... } private void pollResult() { Runnable runnable = new Runnable() { @Override public void run() { getResult(); handler.postDelayed(this, 10000); } }; // start after specified time handler.postDelayed(runnable, 10000); } }

单元测试

@RunWith(PowerMockRunner.class) @PrepareForTest({IdvManager.class, Base64.class, Schedulers.class, AndroidSchedulers.class, UserApi.class}) public class UserApiTest { @Mock public UserManager userManager; @Mock private Handler handler; private IdvManager idvManager; private Schedulers schedulers; private UserApi spyUserApi; private TestScheduler testScheduler; private String userID; @Before public void setUp() { MockitoAnnotations.initMocks(this); testScheduler = new TestScheduler(); handler = new Handler(); PowerMockito.suppress(constructor(IdvManager.class)); // mock static PowerMockito.mockStatic(IdvManager.class); PowerMockito.mockStatic(Schedulers.class); PowerMockito.mockStatic(AndroidSchedulers.class); PowerMockito.mockStatic(Base64.class); // Create mock for class idvManager = PowerMockito.mock(IdvManager.class); schedulers = PowerMockito.mock(Schedulers.class); PowerMockito.when(IdvManager.getInstance()).thenReturn(IdvManager); when(idvManager.getUserManager()).thenReturn(userManager); spyUserApi = PowerMockito.spy(UserApi.getInstance()); // TestSchedulerProvider testSchedulerProvider = new TestSchedulerProvider(testScheduler); when(Base64.encodeToString((byte[]) any(), anyInt())).thenAnswer(new Answer<Object>() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { return java.util.Base64.getEncoder().encodeToString((byte[]) invocation.getArguments()[0]); } }); when(schedulers.io()).thenReturn(testScheduler); when(AndroidSchedulers.mainThread()).thenReturn(testScheduler); userID = UUID.randomUUID().toString(); } @After public void clearMocks() { //Mockito.framework().clearInlineMocks(); } @Test public void verifyUserData_callsPollResult_returnsResponse() { // Input String docStr = "iVBORw0KGgoAAAANSUhEUgAAAJ4AAACeCAYAAADDhbN7AA....."; // Output JsonObject verifyResponse = new JsonObject(); verifyResponse.addProperty("status", "Response created"); doReturn(Single.just(verifyResponse)).when(userManager).verifyUserData(docStr, docStr); // spy method call spyUserApiManager.verifyUserData(docFrontArr, docFrontArr); testScheduler.triggerActions(); // assert verify(userManager).verifyUserData(docStr, docStr); } }

错误

java.lang.NullPointerException at com.rahul.manager.UserApi.verifyUserData(UserApi.java:60) at com.rahul.manager.UserApiTest.verifyUserData_callsPollResult_returnsResponse(UserApiTest.java:171) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498)

我需要对内部使用RxJava Singles的Singleton类的方法进行单元测试,并使用PowerMock测试框架模拟静态类和方法。我尝试了各种方法来模拟...
java android mockito rx-java powermock
1个回答
0
投票
测试代码很复杂,因为它不可测试且不可扩展。它到处都包含硬编码的依赖项(例如,用户ID,处理程序,几个单例)。如果您决定使用另一种id生成方法或另一种处理程序,则必须重写整个类才能执行此操作。不用硬编码依赖项,而是在构造函数(对于强制性依赖项)或setter(对于可选的依赖项)中要求它们。这将使您的代码可扩展且可测试。完成此操作后,您将看到您的班级包含几个职责,将它们移到单独的班级后,您会得到更好的画面:-)
© www.soinside.com 2019 - 2024. All rights reserved.