Spring WebFlux; Mono.map() 中抛出的单元测试异常

Spring WebFlux; unit testing exception thrown in Mono.map()

我有一些代码 returns Mono<List<UserObject>>。我要做的第一件事是检查 List 是否为空,如果是,则抛出一个 NoUsersFoundException。我的代码如下所示:

IUserDao.java
Mono<List<UserAccount>> getUserProfiles(final Set<UserQueryFilter> filters,
                                       final Set<String> attributes);
GetUserAccount.java
public Mono<UserAccount> doGetUserAccount() {
    return userDao.getUserProfiles(filters, attributes)
                      .map(list -> {
                          if (CollectionUtils.isEmpty(list)) {
                              throw new NoUsersFoundException();
                           }
                           return list;
                       })
                       .map(this::removePermissions)
                       .map(this::removeDuplicates);
}

我想编写一个单元测试来测试 NoUsersFoundExceptionuserDao.getUserProfiles(filters, attributes) return 为空列表时是否抛出。当我将 Mockito#when.thenReturn() 一起使用时,如预期的那样,一旦调用 userDao.getUserProfiles(...),测试将立即 return,而不会继续流向 .map(),其中检查列表并抛出异常。

@Mock
private IUserDao userDao;

private UserPolicies userPolicies;

@BeforeEach
public void init() {

    userPolicies = new UserPolicies(Set.of("XYZ", USER_AFF, "123"),
                                           Set.of(TestUserConstants.ID, TestUserConstants.SUBSCRIPTION_LEVEL));
}

@Test
void shouldThrowExceptionIfNoUsersFound() {

    final Set<UserFilter> filters = new UserFilterBuilder().withId(ID)
                                                           .withSubscription(PREMIUM)
                                                           .build();

    when(userDao.getUserProfiles(filters, userPolicies.getUserAttributeIds()))
                    .thenReturn(Mono.just(Collections.emptyList()));

    testClass = new GetUserAccount(userDao,
                                   userPolicies,
                                   filters,
                                   userPolicies.getUserAttributeIds());

    assertThatThrownBy(() -> testClass.doGetUserAccount()).isInstanceOf(NoUsersFoundException.class);
}

我试过 .thenAnswer() 但它基本上做同样的事情,因为调用的方法不是 void:

userDao.getUserProfiles(filters, userPolicies.getUserAttributeIds()))
                .thenAnswer((Answer<Mono<List>>) invocationOnMock -> Mono.just(Collections.emptyList()));

我看不出在这种情况下使用 reactor.test.StepVerifier 会有什么效果。

我不太明白你在问什么,但我们通常不会在 reactor 中“抛出”异常。我们 return 一个 Mono#error 下游,随着错误向下游传播,不同的操作员将做出相应的反应。

public Mono<List<Foobar> fooBar(filters, attributes) {
    return daoObject.getUserProfiles(filters, attributes)
                      .map(list -> {
                          if (CollectionUtils.isEmpty(list)) {
                              // Return a mono#error
                              return Mono.error( ... );
                           }
                           return list;
                       })
}

然后使用步骤验证程序进行测试。使用 expectNextexpectError.

// Happy case
StepVerifier.create( 
    fooBar(filters, attributes)) 
    .expectNext( ... ) 
    .verify();

// Sad case
StepVerifier.create( 
    fooBar(filters, attributes)) 
    .expectError( ... ) 
    .verify();