Reputation: 4574
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
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
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
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
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