Using Assert::ExpectException with Native Unit Testing in VS11

 

The native unit testing capabilities in VS11 beta are very cool indeed.  Being mainly a managed code developer, I was left wondering how to pass a test if an expected exception is thrown (a al the [ExpectedException] attribute I’ve used with MS-TEST in managed code unit tests.  With the native unit testing capabilities in VS11, there is no ExpectedException attribute, but there is a static Assert::ExpectException method that we use to verify that our code under test throws an exception.  It accepts a lambda or a functor as a parameter.  Being a beta, I hadn’t seen too many examples, so I’ve included a couple below.

 

    1:          TEST_METHOD(ExpectCallThrowException)
    2:          {
    3:              auto func = [this] { throwException();};
    4:              Assert::ExpectException<int>(func);
    5:          }
    6:   
    7:          void throwException()
    8:          {
    9:              throw 1;
   10:          }
  
  

Here is a more realistic example, where my BankAccount class throws an invalid_argument exception if a zero amount is passed in as the parameter.

    1:  double BankAccount::Debit(double amount)
    2:  {
    3:      if(amount == 0)
    4:      {
    5:          throw std::invalid_argument("amount");
    6:      }
    7:      balance -= amount;
    8:      return balance;
    9:  }
   10:   
   11:  double BankAccount::Credit(double amount)
   12:  {
   13:      if(amount == 0)
   14:      {
   15:          throw std::invalid_argument("amount");
   16:      }
   17:      balance += amount;
   18:      return balance;
   19:  }

And for my test code, we have examples below of using Assert::ExpectException with a lambda, or by catching the exception ourselves and verifying in the test.

    1:      
    2:  #include <stdexcept>
    3:  #include <functional>
    4:   
    5:          TEST_METHOD(InvalidArgumentIsThrownWhenDebittingZero)
    6:          {
    7:              BankAccount* sut = new BankAccount();
    8:              double amount = 0.00;
    9:              function<double (void)> f1 = [sut] { return sut->Debit(0.00); };
   10:              Assert::ExpectException<invalid_argument>(f1);
   11:          }
   12:   
   13:          TEST_METHOD(ExceptionThrownWhenCreditAmountIsZero)
   14:          {
   15:              BankAccount* sut = new BankAccount();
   16:              double amount = 0.00;
   17:              bool exceptionThrown = false;
   18:              try
   19:              {
   20:                  sut->Credit(amount);
   21:              }catch(invalid_argument& ex)
   22:              {
   23:                  auto desc = ex.what();
   24:                  exceptionThrown = true;
   25:              }
   26:              Assert::IsTrue(exceptionThrown);
   27:          }

I haven’t seen too many examples of using Assert::ExpectException, so hopefully this is helpful.  If this all changes for the VS11 RTM, I’ll be sure to update this post.

Thanks,
-Dan