Kerry7777
Kerry7777

Reputation: 4574

Simple Unit Testing - Parse Invalid Input To Throw Error C# Visual Studio

I have a very basic method that divides two double values. For unit testing I want to include a invalid input (string) to throw error message or exception. What is most simple way to parse the value or fail the test (expected)?

CalculatorClass.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Calculator
{
    public class CalculatorClass
    {
        //METHODS
        public double Divide(double num1, double num2)
        {
            double result = num1 / num2;
            return result;
        }
    }
}

UnitTest1.cs

using System;
using Calculator; //ADD REFERENCE
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace CalcMethodTest
{
    //AreEqual
    //AreNotEqual
    //AreNotSame
    //AreSame
    //Equals
    //Fail
    //Inconclusive
    //IsFalse
    //IsInstanceOfType
    //IsNotNull
    //IsNull
    //IsTrue
    //ReplaceNullChars

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void _1_3_Test_Divide_Input_Seven_2_Output_Error()
        {
            //ARRANGE
            CalculatorClass calcObj = new CalculatorClass();
            string expectedOutput = "Error - Invalid Input";
            //ACT

            //----HERE WRONG DATA TYPE FOR TESTING----
            double result = calcObj.Divide("Seven", 2);
            //ASSERT
            Assert.AreEqual(expectedOutput, result);
        }
    }
}

Upvotes: 1

Views: 2184

Answers (4)

Ian
Ian

Reputation: 30813

Since your Divide method takes input of double,double the string wrong data type you use cannot be used as input.

In order to allow the input to be string or number, I suggest you to change the argument type to a base class common to both (say, object) and then expand the Divide by trying to parse the data - returning false if the process cannot be finished (or if the exception occur, up to you), similar to TryParse method provided by .Net. You can also extend the out variable to include the error string if you find it suitable.

Also, more appropriate name would be TryDivide than Divide:

namespace Calculator {
  public class CalculatorClass {
    //METHODS
    public bool TryDivide(object num1, object num2, out double doubleVal, out string errorString) {
      doubleVal = 0;
      errorString = string.Empty;

      try {
        if (num1 == null || num2 == null) {
          errorString = "number(s) cannot be null";
          return false;
        }

        double num = 0, den = 0;
        bool parseResult;

        if (num1 is double)
          num = (double)num1;
        else {
          parseResult = double.TryParse(num1.ToString(), out num);
          if (!parseResult) {
            errorString = "numerator cannot be parsed as double";
            return false;
          }
        }

        if (num2 is double)
          den = (double)num2;
        else {
          parseResult = double.TryParse(num2.ToString(), out den);
          if (!parseResult) {
            errorString = "denominator cannot be parsed as double";
            return false;
          }
        }

        doubleVal = num / den;
        return true;

      } catch (Exception ex) {
        errorString = ex.ToString();
        return false; //may also be changed to throw
      }
    }
  }
}

Just then you will be able call your TryDivide with string input:

double doubleResult;
string errorString;
bool result = calcObj.TryDivide("Seven", 2, out doubleResult, out errorString);
if (!result){ //something is wrong
    Console.WriteLine(errorString);        
}

Upvotes: 1

Kerry7777
Kerry7777

Reputation: 4574

This seems to work:

[TestMethod]
public void _1_3_Test_Divide_Input_Seven_2_Output_Error()
{
    //ARRANGE
    CalculatorClass calcObj = new CalculatorClass();
    string expectedOutput = "Error - Invalid Input";
    //ACT
    //----CHANGED TO STRING. THEN CAST BACK TO DOUBLE INSIDE METHOD----
    string result = calcObj.Divide("Seven", "2");
    //ASSERT
    Assert.AreEqual(expectedOutput, result);
}

Method:

public string Divide(string num1, string num2)
{
    string resultMsg = "";

    try
    {
        double num1Dbl = double.Parse(num1);
        double num2Dbl = double.Parse(num2);
        double result = num1Dbl / num2Dbl;
        resultMsg = result.ToString();
        return resultMsg;
    }
    catch (FormatException error)
    {
        resultMsg = "Error - Invalid Input";
        return resultMsg;
    }
}

Upvotes: 0

Acha Bill
Acha Bill

Reputation: 1255

If all you want is to test exception handling in unit tests and how you can fail tests by passing wrong arguments, look at this example.

public class Sum
{
    //Returns the sum of 2 positive odd integers
    //If either of arguments is even, return -1
    //If either of arguments is negative, throw exception
    public int PositiveSumOddOnly(int a, int b)
    {
        if(a < 0 || b < 0)
            throw new InvalidArgumentException("One or more of your arguments is negative");
        if(a%2 == 0 || b%2 == 0)
            return -1;
        return a + b;
    }
}

[TestClass]
public class Sum_Test
{
    [TestMethod]
    public int PositiveSumOddOnly_ShouldThrowInvalidArgumentExecption(int a, int b)
    {
        Sum s = new Sum();
        try
        {
            int r = s.PositivesumOddOnly(1,-1);
        }
        catch(InvalidArgumentException e)
        {
            Assert.AreEqual("One or more of your arguments is negative", e.Message);
        }
    }
    [TestMethod]
    public int PositiveSumOddOnly_ShouldReturnNegativeOne(int a, int b)
    {
        Sum s = new Sum();
        int r = s.PositiveSumOddOnly(1,2);
        Assert.AreEqual(r,-1);
    }

    [TestMethod]
    public int PositiveSumOddOnly_ShouldReturnSumOfAandB(int a, int b)
    {
        Sum s = new Sum();
        int r = s.PositiveSumOddOnly(1,1);
        Assert.AreEqual(r,2);
    }
}

Upvotes: 0

slandau
slandau

Reputation: 1

You are not able to pass a string where a double parameter is expected. If you absolutely need to be able to pass a string parameter to this method, you should not expect it to fail based on it being an invalid type - only if the conversion to a double failed. In that case, I'd attempt some rudimentary parsing of a string to a double (however in that case you'd probably only want to parse "7", not "seven" - up to you though).

What you have written will never be able to get tested, purely because it will never compile using C#.

Upvotes: 0

Related Questions