# Run unit tests · A simple Chromia app with Rell and React · Learn Chromia

> Once you have added input verification, running the tests produces failures with the message "User must sign this operation."

Source: https://chromia.com/learn/my-news-feed/module-one/input-verification/tests/

A simple Chromia app with Rell and ReactLesson 15 of 27

1. [01Building a simple Chromia app with Rell, React and FT4](https://chromia.com/learn/my-news-feed/introduction/)
2. [02Project setup complete](https://chromia.com/learn/my-news-feed/setup/)

Module 1: A Rell backend with FT accounts

1. [03Overview](https://chromia.com/learn/my-news-feed/module-one/)
2. [04Part 1: Designing the database schema](https://chromia.com/learn/my-news-feed/module-one/data-modeling/)
3. [05The data model](https://chromia.com/learn/my-news-feed/module-one/data-modeling/tables/)
4. [06Code the model in Rell](https://chromia.com/learn/my-news-feed/module-one/data-modeling/model/)
5. [07Part 2: Set up accounts](https://chromia.com/learn/my-news-feed/module-one/create-accounts/)
6. [08FT4 accounts configuration](https://chromia.com/learn/my-news-feed/module-one/create-accounts/install-configure-ft4/)
7. [09Authentication with FT4 accounts](https://chromia.com/learn/my-news-feed/module-one/create-accounts/authentication/)
8. [10Part 3: A closer look at operations and queries](https://chromia.com/learn/my-news-feed/module-one/operations-queries/)
9. [11Basic operations](https://chromia.com/learn/my-news-feed/module-one/operations-queries/basic-operations/)
10. [12Basic queries](https://chromia.com/learn/my-news-feed/module-one/operations-queries/write-queries/)
11. [13Part 4: Validating and verifying input](https://chromia.com/learn/my-news-feed/module-one/input-verification/)
12. [14Verify inputs](https://chromia.com/learn/my-news-feed/module-one/input-verification/input-verification/)
13. [15Run unit tests](https://chromia.com/learn/my-news-feed/module-one/input-verification/tests/)
14. [16Part 5: How the dapp project is organized](https://chromia.com/learn/my-news-feed/module-one/project-structure/)
15. [17Work with Rell modules](https://chromia.com/learn/my-news-feed/module-one/project-structure/modules/)
16. [18Add modules to your dapp](https://chromia.com/learn/my-news-feed/module-one/project-structure/incorporate-modules/)
17. [19Part 6: Sign up users with an EVM wallet](https://chromia.com/learn/my-news-feed/module-one/register-evm-accounts/)
18. [20Sign up accounts with EVM wallets](https://chromia.com/learn/my-news-feed/module-one/register-evm-accounts/register-evm-accounts/)
19. [21Test the registration](https://chromia.com/learn/my-news-feed/module-one/register-evm-accounts/test-registration/)

Module 2: The React project

1. [22Overview](https://chromia.com/learn/my-news-feed/module-two/)
2. [23Set up the project](https://chromia.com/learn/my-news-feed/module-two/setup/)
3. [24Project scaffold](https://chromia.com/learn/my-news-feed/module-two/scaffold/)
4. [25Connect the client](https://chromia.com/learn/my-news-feed/module-two/connecting-the-client/)
5. [26Summary and manual testing](https://chromia.com/learn/my-news-feed/module-two/summary-and-tests/)

1. [27What is next?](https://chromia.com/learn/my-news-feed/what-next/)

[Learn](https://chromia.com/learn/)[A simple Chromia app with Rell and React](https://chromia.com/learn/my-news-feed/)

15 / 27Module 1: A Rell backend with FT accountsBeginner

# Run unit tests

Once you have added input verification, running the tests produces failures with the message "User must sign this operation."  This is the expected result: the original tests never signed their transactions, so the new checks reject them.

To make the tests pass, sign each test transaction with `.sign(keypair)`. In `test_create_entities`, for example, Alice's keypair signs the transaction:

src/test/news\_feed\_test.rell

```
val alice_kp = rell.test.keypairs.alice; // <--

function test_create_entities() {
    rell.test.tx()
        .op(create_user("Alice", alice))
        .op(create_user("Bob", bob))
        .run();
    assert_equals(user @ { } ( @sum 1 ), 2);
    rell.test.tx()
        .op(ft_auth_operation_for(alice))
        .op(follow_user(bob))
        .op(ft_auth_operation_for(alice))
        .op(make_post("My post"))
        .sign(alice_kp)
        .run();
    assert_true(is_following(alice, bob));
    assert_equals(follower @ { } ( @sum 1 ), 1);
    assert_equals(post @ { } ( @sum 1 ), 1);
    rell.test.tx()
        .op(ft_auth_operation_for(alice))
        .op(unfollow_user(bob))
        .sign(alice_kp)
        .run();
    assert_equals(follower @ { } ( @sum 1 ), 0);
}
```

The second test, `test_follower_calculation`, needs a signature on its transaction as well:

src/test/news\_feed\_test.rell

```
function test_follower_calculation() {
    ...
    rell.test.tx()
        .op(ft_auth_operation_for(alice))
        .op(follow_user(bob))
        .op(ft_auth_operation_for(alice))
        .op(follow_user(charlie))
        .sign(alice_kp)                 // <--
        .run();
    ...
}
```

The last test involves two users. Alice signs the `follow_user` transaction, and Bob signs the `make_post` transactions. Add a constant for Bob's keypair and update the test as shown:

src/test/news\_feed\_test.rell

```
val bob_kp = rell.test.keypairs.bob;

function test_pagination_of_posts() {
    rell.test.tx()
        .op(create_user("Alice", alice))
        .op(create_user("Bob", bob)).run();
    rell.test.tx()
        .op(ft_auth_operation_for(alice))
        .op(follow_user(bob))
        .sign(alice_kp)                // <--
        .run();

    for (i in range(5)) {
        rell.test.tx().op(make_post(bob, "Content %d".format(i))).sign(bob_kp).run(); // <--
    }
    ...
}
```

With these changes, every test passes.

## Additional testing

Add one more test to verify that a user cannot impersonate another user and that input validation behaves correctly:

src/test/news\_feed\_test.rell

```
val charlie_kp = rell.test.keypairs.charlie;

function test_input_verification() {
    rell.test.tx()
        .op(create_user("Alice", alice))
        .op(create_user("Bob", bob)).run();

    // Bob cannot impersonate alice
    rell.test.tx()
        .op(ft_auth_operation_for(alice))
        .op(follow_user(bob))
        .sign(bob_kp)
        .run_must_fail();
    rell.test.tx()
        .op(ft_auth_operation_for(alice))
        .op(make_post("My malicous post"))
        .sign(bob_kp)
        .run_must_fail();

    // Alice cannot follow non-existing charlie
    val f1 = rell.test.tx()
        .op(ft_auth_operation_for(alice))
        .op(follow_user(charlie))
        .sign(alice_kp)
        .run_must_fail();
    assert_true(f1.message.contains("does not exist"));

    // Charlie cannot create post since he does not exist
    val f2 = rell.test.tx()
        .op(make_post("My secret post"))
        .sign(charlie_kp)
        .run_must_fail();
    assert_true(f2.message.contains("Expected at least two operations"));
}
```

You now know how to apply basic input validation to queries and operations. The next module covers more secure, structured account management with the [ft-library](https://docs.chromia.com/build/ft4/intro/).

Written for this site from Chromia’s public course. Code samples are the course’s own.

[← Previous**Verify inputs**](https://chromia.com/learn/my-news-feed/module-one/input-verification/input-verification/)[Next →**Part 5: How the dapp project is organized**](https://chromia.com/learn/my-news-feed/module-one/project-structure/)

On this page

* [Additional testing](#additional-testing)
