Search code examples
javaunit-testinglambdajunitassertj

in JUnit test (java) How to check in a array of array with Assertj librairy?


I want use assertj for cheking a data in array contain a other array.

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
    }

My 2 first tests case are OK. I filter on 'resourceId=010001781LV' and I check account.currency=EUR. I filter on 'resourceId=010001781LV' and I check 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);

but I want filter on 'resourceId=010001781LV' and filter on 'balances(foreach).balanceType=CLBD' and check balanceAmount=10000.

I try lambda in other lambda but I need some help:

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");

I have this error on 2nd 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) -> {})

Solution

  • The point is that expression inside filterOn should return boolean whereas forEach returns void.

    Account id should be "DEF" and all "A" balances should have "10" value.

    @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);
    }