Thread overview
February 16

When I tried to catch exceptions in my unit test, I found that exceptions were not thrown or caught in the unit test blocks. So, I cannot use assertThrown at all. Is this a bug or expected behavior that I don't know?

Using LDC 1.36.0 on Windows.

https://github.com/aferust/evalex/blob/main/source/evalex.d#L694

February 16
This should be working.

I don't know what is going on.

All I can suggest is to use a debugger to see if it is indeed throwing and then catching.
February 16

On Friday, 16 February 2024 at 07:54:01 UTC, Richard (Rikki) Andrew Cattermole wrote:

>

This should be working.

I don't know what is going on.

All I can suggest is to use a debugger to see if it is indeed throwing and then catching.

A test code like this works, but unittest doesn't. This is crazy:

import std.stdio;
import evalex;

    void main(){
        string text = "2 + * 3";
        try {
            auto evaluator = new Eval!double(text);
            auto result = evaluator.result;
            writeln(result);
        }catch (ParserException e){
            writeln(e.msg);
        }

    }
    ```
February 16

On Friday, 16 February 2024 at 07:43:24 UTC, Ferhat Kurtulmuş wrote:

>

When I tried to catch exceptions in my unit test, I found that exceptions were not thrown or caught in the unit test blocks. So, I cannot use assertThrown at all. Is this a bug or expected behavior that I don't know?

Using LDC 1.36.0 on Windows.

https://github.com/aferust/evalex/blob/main/source/evalex.d#L694

Even a test code like this does not work:

string division(int a, int b) {
   string result = "";

   try {
      if( b == 0 ) {
         throw new Exception("Cannot divide by zero!");
      } else {
         result = format("%s",a/b);
      }
   } catch (Exception e) {
      result = e.msg;
   }

   return result;
}

assertThrown({division(50, 0);});
February 16
On Friday, February 16, 2024 1:06:26 AM MST Ferhat Kurtulmuş via Digitalmars- d-learn wrote:
> On Friday, 16 February 2024 at 07:43:24 UTC, Ferhat Kurtulmuş
>
> wrote:
> > When I tried to catch exceptions in my unit test, I found that exceptions were not thrown or caught in the unit test blocks. So, I cannot use assertThrown at all. Is this a bug or expected behavior that I don't know?
> >
> > Using LDC 1.36.0 on Windows.
> >
> > https://github.com/aferust/evalex/blob/main/source/evalex.d#L694
>
> Even a test code like this does not work:
>
> ```d
> string division(int a, int b) {
>     string result = "";
>
>     try {
>        if( b == 0 ) {
>           throw new Exception("Cannot divide by zero!");
>        } else {
>           result = format("%s",a/b);
>        }
>     } catch (Exception e) {
>        result = e.msg;
>     }
>
>     return result;
> }
>
> assertThrown({division(50, 0);});
> ```

1. assertThrown does not test whether something somewhere in what you called threw an exception. It asserts that it catches an exception. Your example here is catching the exception and returning so the exception never escapes the division function, and there's nothing for assertThrown to catch.

2. You're just passing a lambda to assertThrown without actually calling it. The first argument to assertThrown is lazy, which means that it creates a delegate from what you pass to it. assertThrown then calls that delegate. However, in your example here, that delegate just contains a lambda declaration, so it would basically be the equivalent of having

void foo()
{
    {division(50, 0);};
}

which would be like doing

void foo()
{
    int i;
}

in the sense that the function just contains a declaration that does nothing.

The normal thing to do here would be to not use a lambda at all, since it just contains a function call.

    assertThrown(division(50, 0));

but in cases where you actually need a lambda, because you're doing something more complex than simply calling a function, you need to call it when passing it. e.g.

    assertThrown({division(50, 0);}());

That then would be like declaring

void foo()
{
    {division(50, 0);}();
}

so when assertThrown calls the delegate, the delegate actually calls the lambda. But regardless, the expression that you pass to assertThrown has to actually throw an Exception if you want it to pass, and division doesn't do that, because it catches the Exception internally.

If what you want to test is whether something deeper down the stack threw an Exception that got caught, then you're out of luck. That's the sort of thing where you'd need a debugger or some other tool that tracked what the code was doing. assertThrown is just a simple library function that helps you test that an expression throws an exception - generally with the idea that it allows you to test that a piece of code throws an exception when it's suposed to (e.g. because you gave it bad input).

void assertThrown(T : Throwable = Exception, E)
                 (lazy E expression,
                  string msg = null,
                  string file = __FILE__,
                  size_t line = __LINE__)
{
    import core.exception : AssertError;

    try
        expression();
    catch (T)
        return;

    static if (!is(immutable E == immutable noreturn))
        throw new AssertError("assertThrown failed: No " ~ T.stringof ~
                              " was thrown" ~
                              (msg.length == 0 ? "." : ": ") ~ msg,
                          file, line);
}

- Jonathan M Davis




February 16
On Friday, 16 February 2024 at 08:48:08 UTC, Jonathan M Davis wrote:
> On Friday, February 16, 2024 1:06:26 AM MST Ferhat Kurtulmuş via Digitalmars- d-learn wrote:
>> [...]
>
> 1. assertThrown does not test whether something somewhere in what you called threw an exception. It asserts that it catches an exception. Your example here is catching the exception and returning so the exception never escapes the division function, and there's nothing for assertThrown to catch.
>
> [...]

Hi Jonathan, thank you for clearly explaining in detail how it works. I added trailing parenthesis to the lambda inside assertThrown, which worked as expected.

Ferhat