Akh*_*Dad 1 android unit-testing mocking crashlytics
我正在使用MVP架构来构建我的应用程序。我的演示者调用了一个DataManager,它负责从网络或数据库中获取数据。当我使用RxJava时,我在Presenter中订阅了Observers并将适当的状态传递给UI。我的服务层具有Android上下文,它还将创建我自己的类型的Exception,该异常也引用了Context。
if (isNetworkConnected()) {
final Call<ServiceResponse<AppVersion>> call = mService.getAppVersion();
try {
final Response<ServiceResponse<AppVersion>> response = call.execute();
if (response.isSuccessful()) {
final ServiceResponse<AppVersion> serviceResponse = response.body(); response.body();
if (serviceResponse.isSuccess()) {
subscriber.onNext(serviceResponse.getData());
} else {
subscriber.onError(new CustomException(mContext, response.code(), response.message(), serviceResponse.getErrorList()));
}
} else {
subscriber.onError(new CustomException(mContext, response.code(), response.message(), response.errorBody().string()));
}
} catch (IOException e) {
e.printStackTrace();
subscriber.onError(e);
} finally {
subscriber.onCompleted();
}
} else {
subscriber.onError(new NoInternetException());
}
Run Code Online (Sandbox Code Playgroud)
我的CustomException也将崩溃记录在Crashlytics中。当我对该代码进行单元测试时,我从Crashlytics获取了一个未初始化的异常。因此,我需要模拟logExceptionCrashlytics 的静态方法。但是由于演示者不接受该对象,我应该如何传递此模拟对象?
public staticErrorType getErrorType(Throwable throwable) {
//409: Not handled as its a conflict response code and comes in PUT/POST
if (throwable instanceof IOException) {
return ErrorType.NO_INTERNET;
} else if (throwable instanceof CustomException) {
final int errorCode = ((CustomException) throwable).mErrorCode;
if (errorCode == 404) {
return ErrorType.NOT_FOUND;
} else if (errorCode == 401) {
return ErrorType.UNAUTORISED;
} else if (errorCode == 403) {
return ErrorType.FORBIDDEN;
} else if (errorCode == 500 || errorCode == 502) {
return ErrorType.NO_SERVER_TRY_AGAIN;
} else if (errorCode > 500 && errorCode < 599) {
return ErrorType.NO_SERVER_TRY_LATER;
} else if (errorCode == 1000) {
return ErrorType.NO_COURSE_ENROLLED;
} else if (errorCode == 1001) {
return ErrorType.NO_COURSE_STARTED;
}
}
if (throwable != null) {
Crashlytics.logException(throwable);
}
return ErrorType.SOME_THING_WENT_WRONG;
}
Run Code Online (Sandbox Code Playgroud)
您所遇到的是有人认为静态方法存在问题。静态方法logException()似乎无处不在,但实际上隐藏了真正的依赖关系。由于运行该类现在需要该依赖关系,因此使您的类难以测试。
一个好的解决方案是使用非静态方法创建包装器类。如果我们将此答案中的解决方案应用于您的代码,它将看起来像这样:
public class CrashLyticsWrapper {
public CrashLyticsWrapper() {}
public void logException(Throwable t) {
CrashLytics.logException(t);
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以将其作为需要它的类的依赖项在构造函数中传递。由于它是一个非静态的依赖关系,并且是一个您现在控制的类,因此可以轻松对其进行模拟,并在必要时进行验证。
一个单独的问题:异常就像值对象,并且在大多数情况下,它们不应具有静态或非静态的依赖关系。做这样的事情:
public CustomException extends RuntimeException() {
public CustomException() {
Crashlytics.logException(this); //don't do this!
}
}
Run Code Online (Sandbox Code Playgroud)
编写易碎且不可测试的代码。您可以从子类化异常中重写的构造函数中看到,有一个原因字段,一个消息字段,仅此而已。一个很好的例外范围。如果您需要添加异常附带的功能,则应编写将异常作为数据或参数的单独错误处理程序。这符合SOLID中的“单一职责”原则。
| 归档时间: |
|
| 查看次数: |
1009 次 |
| 最近记录: |