安卓:如何对Rxjava Observable进行单元测试



我正在学习android单元测试,我有点拘泥于rxjava observable的单元测试。

我尝试测试的这个方法:

@Override
public Observable<AuthenticationUsingSqlEntity> logInUsingSql(String token, String ssid) {
SqlRepo sqlRepo = new SqlRepo();
return sqlRepo.authenticate(token, ssid);
}

我创建了一个简单的ArgumentCaptor来测试已经相同的输入,并通过了单元测试。我想做的是测试sql改进响应,但我做不到。

我想知道为什么您提供一些方法调用,而不是要测试的实际SqlRepo方法?结果是,这只能得到一个普遍的答案。现在还不清楚,你说的是哪个版本;我假设是版本2。然而,为了测试Observable本身,可以简单地将Observable.test()链接,有TestObserver,但也有TestSubscriber,它可以用于测试订户,还有TestScheduler,它可以用来调度模拟RX事件。很明显,所提供的方法调用不足以编写正确的测试,因为要测试的方法(对我来说(完全未知。

在该方法的测试中,不应该使用ArgumentCaptor。通常,当您需要对接收或创建对象的方法编写测试,并且希望检查该对象作为参数的有效性(例如,电子邮件地址的格式是否正确(时,会使用它。

// Create a mock of the OtherClass
OtherClass other = mock(OtherClass.class);

// Run the foo method with the mock
new A().foo(other);

// Capture the argument of the doSomething function
ArgumentCaptor<SomeData> captor = ArgumentCaptor.forClass(SomeData.class);
verify(other, times(1)).doSomething(captor.capture());

// Assert the argument
SomeData actual = captor.getValue();
assertEquals("Some inner data", actual.innerData);

对该方法唯一可以使用的测试是检查该方法是否调用sqlRepo.authenticate的测试。如果你想检查来自Reform的响应,那么你需要专门对sqlRepo类中的方法"authenticate"编写一个测试。此外,如果您想专门在Observable上编写一个测试,那么您可以使用TestObserver。然后,您可以使用各种方法来检查您将收到的结果。

这里有一个例子:

someService.authenticate()
.test()
.assertNoErrors()
.assertValue( someValue -> 
//check if the value is correct
);

假设您的类类似于以下内容:

class LoginManager {
@Override
public Observable<AuthenticationUsingSqlEntity> logInUsingSql(String token, String ssid) {
SqlRepo sqlRepo = new SqlRepo();
return sqlRepo.authenticate(token, ssid);
}
}

然后通过单元测试,我们旨在验证单元或函数的逻辑。

从这个角度来看,方法的逻辑是将登录操作卸载到SqlRepo类。我们必须验证这个逻辑。为了做到这一点,我们检查是否调用了Sqlrepo的authenticate函数来响应logInUsingSql((方法的调用。我们通过:

loginManagerClassUnderTest = Mockito.spy(loginManagerClassUnderTest);
mockSqlRepo mockSqlRepo = Mockito.mock(mockSqlRepo.class);
doReturn(mockSqlRepo).when(loginManagerClassUnderTest).getSqlRepo();
loginManagerClassUnderTest.logInUsingsql("mockToken", "mockSsid");
ArgumentCaptor<String> tokenCaptor = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> ssidCaptor = ArgumentCaptor.forClass(String.class);
verify(mockSqlRepo).authenticate(tokenCaptor.capture(), ssidCaptor.capture());
assertEquals("mockToken", tokenCaptor.getValue());
assertEquals("mockSsid", ssidCaptor.getValue());

正如您所看到的,LoginManager依赖于SqlRepo类,我们必须为这种依赖提供一个mock,以便确保测试是在隔离的情况下进行的。所以将Loginmanager函数更改为:

class LoginManager {

@Override
public Observable<AuthenticationUsingSqlEntity> logInUsingSql(String token, String ssid) {
SqlRepo sqlRepo = getSqlRepo();
return sqlRepo.authenticate(token, ssid);
}
public SqlRepo getSqlRepo() {
return new SqlRepo();
}
}

最新更新