单元测试 - 已订阅验证Observable
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单元测试 - 已订阅验证Observable相关的知识,希望对你有一定的参考价值。
我有这样的java代码
mDataManager.getObservable("hello").subscribe( subscriber );
而我想要verify
以下Observable是.subscribe()
我试图模仿getObservable()
和verify
Observable<Response> res = mock(Observable.class);
when(mDataManager.getObservable("hello")).thenReturn(res);
verify(res).subscribe();
但是有一个错误
Caused by: java.lang.IllegalStateException: onSubscribe function can not be null.
at rx.Observable.subscribe(Observable.java:8167)
at rx.Observable.subscribe(Observable.java:8158)
at rx.Observable.subscribe(Observable.java:7962)
....
Caused by: rx.exceptions.OnErrorThrowable$OnNextValue: OnError while emitting onNext value: omni.neo.hk.omniapiservice.v4.model.external.UserLoginBean.class
at rx.exceptions.OnErrorThrowable.addValueAsLastCause(OnErrorThrowable.java:109)
at rx.exceptions.Exceptions.throwOrReport(Exceptions.java:187)
at rx.internal.operators.OperatorDoOnEach$1.onNext(OperatorDoOnEach.java:82)
... 48 more
我认为mock
不可能是一个Observable在这里,但没有一个嘲笑的Observable我不能doverify(res).subscribe()
在这种情况下的任何建议?
我发现RxJava提供了一个名为TestSubject
的类
你可以像这样创建它
private TestScheduler eventsScheduler = new TestScheduler();
private TestSubject<MyEvent> eventObservable = TestSubject.create(eventsScheduler);
这将为您提供返回布尔值的hasObservers()
方法。
@Test
public void testSubscription(){
myTestClass.init(eventObservable);
assertTrue(eventObservable.hasObservers());
}
此外,TestSubject还可以让您在发送事件时获得完美的时间。
eventObservable.onNext(new MyEvent());
eventsScheduler.triggerActions();
也许你可以使用Observable.onSubscribe
方法和RunTestOnContext
规则? TestContext
可以为您提供Async
对象,只有在完成后才会终止测试。我认为,如果你将它与Observable#doOnSubscribe
结合起来,你可以达到理想的行为。
但是,使用Async
有时可能会有点混乱。在下面的示例中,如果observable从未订阅,则doOnSubscribe
函数将永远不会被评估,并且您的测试不会终止。
例:
@RunWith(VertxUnitRunner.class)
public class SubscriptionTest {
@Rule
public RunTestOnContext vertxRule = new RunTestOnContext();
@Test
public void observableMustBeSubscribed(final TestContext context) {
final Async async = context.async();
final Observable<String> observable = Observable.just("hello").doOnSubscribe(async::complete);
final Manager mock = mock(Manager.class);
when(mock.getObservable()).thenReturn(observable);
mock.getObservable().subscribe();
}
interface Manager {
Observable<String> getObservable();
}
}
我不确定我是在回答这个被问到的问题,但我想是的......
可以创建单元测试,以检查是否已对可观察的订阅进行了订阅。请注意,在RxJava 1.x中,TestSubject支持此功能,但Subject实现可以促进该功能。 TestSubject是dropped for RxJava 2。
不要试图像原始海报那样试图模仿observable,而是使用PublishSubject,运行业务逻辑,然后使用发布主题来查看是否正在观察Observable。下面是一些验证此测试的测试代码。测试在我运行时通过。
有关代码的说明,请参阅代码注释。就个人而言,这个测试似乎是其他测试的冗余,可以验证控制器如何处理数据。如果控制器从未订阅并从数据服务接收数据,那么其他测试将失败。另一方面,测试取消订阅有助于避免内存泄漏,这可能是很高的价值。
import org.junit.Test;
import io.reactivex.Observable;
import io.reactivex.disposables.Disposable;
import io.reactivex.subjects.PublishSubject;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
/**
* Tests whether it is possible to test whether a controller properly unsubscribes from an Observable.
*/
public class SubscribeUnsubscribeTests {
/**
* A service that returns a stream of strings.
*/
interface StringService {
Observable<String> getStrings();
}
/**
* A controller that requests strings from the {@link StringService} and logs them
* to system out as they are received.
*/
class StringLoggingController {
private StringService stringService;
private Disposable stringSubscriptionDisposable;
public StringLoggingController(StringService stringService) {
this.stringService = stringService;
}
/**
* Causese the controller to begin strings request and logging.
*/
public void start() {
stringSubscriptionDisposable = stringService.getStrings()
.subscribe(string -> System.out.print(string));
}
public void stop() {
if (stringSubscriptionDisposable != null) {
if (!stringSubscriptionDisposable.isDisposed()) {
stringSubscriptionDisposable.dispose();
stringSubscriptionDisposable = null;
}
}
}
}
/**
* A {@link StringService} that can report whether {@link StringService#getStrings()}
* has observers.
*/
class ReportIsSubscribedStringService implements StringService {
private PublishSubject<String> publishSubject = PublishSubject.create();
public Observable<String> getStrings() {
return publishSubject;
}
/**
* @return true if the {@link #getStrings()} observable has observers.
*/
public boolean stringsAreBeingObserved() {
return publishSubject.hasObservers();
}
}
/**
* Verifies that the {@link StringLoggingController} is subscribing to the service.
*/
@Test
public void stringsLoggingControllerSubscribesToStringService() {
ReportIsSubscribedStringService service = new ReportIsSubscribedStringService();
StringLoggingController controller = new StringLoggingController(service);
controller.start();
assertTrue(service.stringsAreBeingObserved());
}
/**
* Verifies that the {@link StringLoggingController} is unsubscribing from the service.
*/
@Test
public void stringsLoggingControllerUnsubscribesFromStringService() {
ReportIsSubscribedStringService service = new ReportIsSubscribedStringService();
StringLoggingController controller = new StringLoggingController(service);
controller.start();
controller.stop();
assertFalse(service.stringsAreBeingObserved());
}
}
- 编辑 - 我之前写过,我无法测试取消订阅。我确实弄清楚如何测试。事实证明我的测试失败了,因为测试的代码没有正确取消订阅(哈哈 - 测试工作,去图)。我已经更新了上面的代码,以说明测试订阅和取消订阅。
我今天花了几个小时意识到这是一个愚蠢的错误。如果您使用的是PowerMockito,请检查您的@PrepareForTest。
@PrepareForTest({Observable.class})
也别忘了嘲笑它。我是在@before上做的:
PowerMockito.mockStatic(Observable.class);
我希望它可以提供帮助。谢谢
以上是关于单元测试 - 已订阅验证Observable的主要内容,如果未能解决你的问题,请参考以下文章
从服务返回的 Observable 的单元测试值(使用异步管道)
在 RxSwift 中订阅 Observable 或 Driver 花费的时间太长