В тесте JUnit (Java) Как проверить массив массива с помощью библиотеки Assertj?

Я хочу использовать assertj для проверки данных в массиве, содержащем другой массив.

accounts: [class AccountResource {
        resourceId: 010001781LV
        bicFi: null
        accountId: null
        name: Livret A Rosalie
        details: LIVRET A
        linkedAccount: null
        usage: PRIV
        cashAccountType: null
        product: LVA
        currency: EUR
        balances: [class BalanceResource {
            name: null
            balanceAmount: class AmountType {
                currency: EUR
                amount: 10000
            }
            balanceType: CLBD
            lastChangeDateTime: null
            referenceDate: 2018-05-31
            lastCommittedTransaction: null
        }, class BalanceResource {
            name: null
            balanceAmount: class AmountType {
                currency: EUR
                amount: 10000
            }
            balanceType: XPCD
            lastChangeDateTime: null
            referenceDate: 2018-05-31
            lastCommittedTransaction: null
        }]
        psuStatus: Account Holder
        links: null
    }

Мои 2 первых тестовых случая в порядке. Я фильтрую по 'resourceId=010001781LV' и проверяю account.currency=EUR. Я фильтрую по 'resourceId=010001781LV' и проверяю account.balances.size()=2.

assertThat(halAccounts.getAccounts())
        .filteredOn(account -> account.getResourceId().equals("010001781LV"))
        .extracting(account -> account.getCurrency())
        .containsExactly("EUR");
assertThat(halAccounts.getAccounts())
        .filteredOn(account -> account.getResourceId().equals("010001781LV"))
        .extracting(account -> account.getBalances().size())
        .containsExactly(2);

но я хочу, чтобы фильтр по 'resourceId=010001781LV' и фильтр по 'балансам (foreach).balanceType=CLBD' и проверки balanceAmount=10000.

Я пробую лямбду в другой лямбде, но мне нужна помощь:

assertThat(halAccounts.getAccounts())
    .filteredOn(account -> account.getResourceId().equals("010001781LV"))
    .filteredOn(account -> account.getBalances().forEach(balance -> {
        balance.getBalanceAmount().getAmount().equals("10000");
    }))
    .extracting(balance -> balance.getBalanceAmount().getAmount())
    .contains("1000");

У меня эта ошибка на 2-й filteredOn :

Multiple markers at this line
    - The target type of this expression must be a functional interface
    - The method filteredOn(Condition<? super AccountResource>) in the type AbstractIterableAssert<ListAssert<AccountResource>,List<? 
     extends AccountResource>,AccountResource,ObjectAssert<AccountResource>> is not applicable for the arguments ((<no type> account) -> {})

2 ответа

Решение

Дело в том, что выражение внутри filterOn должен вернуться boolean в то время как forEach возвращается void,

Идентификатор счета должен быть "DEF", а все балансы "A" должны иметь значение "10".

@Test
void test() {
    Account wrongAcc = new Account("ABC", Collections.emptyList());
    Account goodAcc = new Account("DEF", Arrays.asList(
            new Balance("A", "10"),
            new Balance("A", "10"),
            new Balance("B", "20")
    ));
    Account wrongBalanceAcc = new Account("DEF", Arrays.asList(
            new Balance("A", "10"),
            new Balance("A", "20"),
            new Balance("B", "20")
    ));

    List<Account> accountList = Arrays.asList(wrongAcc, goodAcc, wrongBalanceAcc);

    assertThat(accountList)
            .filteredOn(acc -> acc.getId().equals("DEF"))
            .filteredOn(acc ->
                    acc.getBalances()
                            .stream()
                            .noneMatch(balance -> balance.getType().equals("A") && !balance.getAmount().equals("10"))
            ).containsExactly(goodAcc);
}

Если я прав, следующий код не возвращает логическое значение ( forEach не возвращает):

account.getBalances().forEach(balance -> {
    balance.getBalanceAmount().getAmount().equals("10000");
})

это означает, что это не является действительным Predicate быть использованным в

filteredOn(account -> account.getBalances().forEach(balance -> {
    balance.getBalanceAmount().getAmount().equals("10000");
}))

Я считаю, что Java пытается применить filteredOn(Condition) что не возможно.

редактировать

Если у вас есть вопрос, как я могу отфильтровать все счета, равные 10000? тогда вы можете использовать это Predicate (не проверено, но должно быть достаточно близко к тому, что вы хотите):

account -> account.getBalances().stream()
                  .map(balance ->  balance.getBalanceAmount().getAmount())
                  .allMatch(amount -> amount.equals("10000"))

См. https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html

Другие вопросы по тегам