0% found this document useful (0 votes)
39 views28 pages

Nunit and Moq

The document provides a comprehensive guide on using NUnit and Moq for unit testing in C#. It includes exercises on creating testable code, mocking interfaces, and writing unit tests for various classes such as a calculator, mail sender, and player mapper. Additionally, it covers best practices for testing methods, handling exceptions, and validating user inputs.

Uploaded by

abbud5859
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views28 pages

Nunit and Moq

The document provides a comprehensive guide on using NUnit and Moq for unit testing in C#. It includes exercises on creating testable code, mocking interfaces, and writing unit tests for various classes such as a calculator, mail sender, and player mapper. Additionally, it covers best practices for testing methods, handling exceptions, and validating user inputs.

Uploaded by

abbud5859
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 28

NUNIT AND MOQ

1. Moq-Handson

1. Write Testable Code with Moq


Exercise 1: MailSender – Interface & Implementation
// Project: CustomerCommLib
using System.Net;
using System.Net.Mail;

public interface IMailSender


{
bool SendMail(string toAddress, string message);
}

public class MailSender : IMailSender


{
public bool SendMail(string toAddress, string message)
{
MailMessage mail = new MailMessage();
SmtpClient smtpServer = new SmtpClient("smtp.gmail.com")
{
Port = 587,
Credentials = new NetworkCredential("[email protected]",
"password"),
EnableSsl = true
};
mail.From = new MailAddress("[email protected]");
mail.To.Add(toAddress);
mail.Subject = "Test Mail";
mail.Body = message;
smtpServer.Send(mail);
return true;
}
}
Exercise 2: CustomerComm – Class Under Test
public class CustomerComm
{
private readonly IMailSender _mailSender;

public CustomerComm(IMailSender mailSender)


{
_mailSender = mailSender;
}

public bool SendMailToCustomer()


{
return _mailSender.SendMail("[email protected]", "Some Message");
}
}

2. Mock File Object for Unit Tests


Exercise 1: DirectoryExplorer – Interface & Implementation
// Project: MagicFilesLib
using System.Collections.Generic;
using System.IO;

public interface IDirectoryExplorer


{
ICollection<string> GetFiles(string path);
}

public class DirectoryExplorer : IDirectoryExplorer


{
public ICollection<string> GetFiles(string path)
{
return Directory.GetFiles(path);
}
}
3. Mock Database for Unit Tests
Exercise 1: PlayerMapper – Interface & Implementation
// Project: PlayersManagerLib
using System.Data.SqlClient;

public interface IPlayerMapper


{
bool IsPlayerNameExistsInDb(string name);
void AddNewPlayerIntoDb(string name);
}

public class PlayerMapper : IPlayerMapper


{
private readonly string _connectionString =
"Data Source=(local);Initial Catalog=GameDB;Integrated Security=True";

public bool IsPlayerNameExistsInDb(string name)


{
using(SqlConnection connection = new SqlConnection(_connectionString))
{
connection.Open();
using(SqlCommand command = connection.CreateCommand())
{
command.CommandText = "SELECT count(*) FROM Player WHERE
[Name] = @name";
command.Parameters.AddWithValue("@name", name);
return (int)command.ExecuteScalar() > 0;
}
}
}

public void AddNewPlayerIntoDb(string name)


{
using(SqlConnection connection = new SqlConnection(_connectionString))
{
connection.Open();
using(SqlCommand command = connection.CreateCommand())
{
command.CommandText = "INSERT INTO Player ([Name]) VALUES
(@name)";
command.Parameters.AddWithValue("@name", name);
command.ExecuteNonQuery();
}
}
}
}

Exercise 2: Player Class – Consuming the Mapper


public class Player
{
public string Name { get; private set; }
public int Age { get; private set; }
public string Country { get; private set; }
public int NoOfMatches { get; private set; }

public Player(string name, int age, string country, int noOfMatches)


{
Name = name;
Age = age;
Country = country;
NoOfMatches = noOfMatches;
}

public static Player RegisterNewPlayer(string name, IPlayerMapper


playerMapper = null)
{
if (playerMapper == null)
playerMapper = new PlayerMapper();

if (string.IsNullOrWhiteSpace(name))
throw new ArgumentException("Player name can’t be empty.");

if (playerMapper.IsPlayerNameExistsInDb(name))
throw new ArgumentException("Player name already exists.");

playerMapper.AddNewPlayerIntoDb(name);
return new Player(name, 23, "India", 30);
}
}

1. NUNIT-HANDSON

2. Calculator Unit Test Setup

Exercise 1: Create Calculator Library


// Project: CalcLibrary
namespace CalcLibrary
{
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}

public int Subtract(int a, int b)


{
return a - b;
}

public int Multiply(int a, int b)


{
return a * b;
}

public int Divide(int a, int b)


{
return a / b;
}
}
}
Exercise 2: Create NUnit Test Project
// Project: CalcLibrary.Tests
using NUnit.Framework;
using CalcLibrary;

namespace CalcLibrary.Tests
{
[TestFixture]
public class CalculatorTests
{
private Calculator _calc;

[SetUp]
public void Init()
{
_calc = new Calculator();
}

[TearDown]
public void Cleanup()
{
_calc = null;
}

[Test]
public void Add_WhenCalled_ReturnsCorrectSum()
{
int result = _calc.Add(10, 20);
Assert.That(result, Is.EqualTo(30));
}

[TestCase(5, 10, 15)]


[TestCase(-5, -5, -10)]
[TestCase(0, 0, 0)]
public void Add_WithTestCases_ReturnsExpectedResult(int a, int b, int
expected)
{
int result = _calc.Add(a, b);
Assert.That(result, Is.EqualTo(expected));
}
[Test]
[Ignore("Ignore this test temporarily")]
public void Subtract_TestIgnored()
{
Assert.Fail("This test is ignored.");
}
}
}

2. NUnit-Handson

1. Objectives
● Demonstrate parameterized test cases using an example

● Test methods that return a value

○ Use Assert.AreEqual, Assert.Fail, AssertionException

● Test void methods

● Test methods that throw exceptions

○ Use try-catch and verify message/type

● Explain why testing private methods is not beneficial

● Explain mocking framework and its usage (e.g., Moq for mocking DB, file,
etc.)

2. Calculator Library
// Project: CalcLibrary
namespace CalcLibrary
{
public class Calculator
{
private int _result;
public int Result => _result;

public int Add(int a, int b)


{
_result = a + b;
return _result;
}

public int Subtract(int a, int b)


{
_result = a - b;
return _result;
}

public int Multiply(int a, int b)


{
_result = a * b;
return _result;
}

public int Divide(int a, int b)


{
if (b == 0)
throw new ArgumentException("Divisor cannot be zero");
_result = a / b;
return _result;
}

public void AllClear()


{
_result = 0;
}
}
}

3. NUnit Test Cases


// Project: CalcLibrary.Tests
using NUnit.Framework;
using CalcLibrary;
using System;

namespace CalcLibrary.Tests
{
[TestFixture]
public class CalculatorTests
{
private Calculator _calc;

[SetUp]
public void Setup()
{
_calc = new Calculator();
}

// 1. Test Subtraction - Parameterized


[TestCase(10, 5, 5)]
[TestCase(0, 0, 0)]
[TestCase(-5, -3, -2)]
[TestCase(100, 25, 75)]
public void Subtract_WithInputs_ReturnsExpected(int a, int b, int
expected)
{
var result = _calc.Subtract(a, b);
Assert.AreEqual(expected, result);
}

// 2. Test Multiplication - Parameterized


[TestCase(2, 3, 6)]
[TestCase(0, 100, 0)]
[TestCase(-4, 5, -20)]
[TestCase(-3, -2, 6)]
public void Multiply_WithInputs_ReturnsExpected(int a, int b, int
expected)
{
var result = _calc.Multiply(a, b);
Assert.AreEqual(expected, result);
}

// 3. Test Division - Parameterized + Exception


[TestCase(10, 2, 5)]
[TestCase(20, 4, 5)]
[TestCase(9, 3, 3)]
public void Divide_WithValidInputs_ReturnsExpected(int a, int b, int
expected)
{
var result = _calc.Divide(a, b);
Assert.AreEqual(expected, result);
}

[Test]
public void Divide_ByZero_ThrowsArgumentException()
{
try
{
var result = _calc.Divide(5, 0);
Assert.Fail("Division by zero"); // Should not reach here
}
catch (ArgumentException ex)
{
Assert.That(ex.Message, Is.EqualTo("Divisor cannot be zero"));
}
}

// 4. Test Void Method - AllClear


[Test]
public void TestAddAndClear()
{
var result = _calc.Add(4, 6);
Assert.AreEqual(10, result);
_calc.AllClear();
Assert.AreEqual(0, _calc.Result);
}
}
}

3.NUNIT HANDS ON
1. Source: URL Host Name Parser

Exercise 1: UtilLib – Class & Method to Test


// Project: UtilLib
namespace UtilLib
{
public class UrlHostNameParser
{
public string ParseHostName(string url)
{
if (string.IsNullOrWhiteSpace(url))
return "Invalid URL";

try
{
var uri = new Uri(url);
return uri.Host;
}
catch (UriFormatException)
{
return "Invalid URL";
}
}
}
}

2. NUnit Test Project – UtilLib.Tests

Exercise 2: Unit Test Setup & Structure


// Project: UtilLib.Tests
using NUnit.Framework;
using UtilLib;

namespace UtilLib.Tests
{
[TestFixture]
public class UrlHostNameParserTests
{
private UrlHostNameParser _parser;
[SetUp]
public void SetUp()
{
_parser = new UrlHostNameParser();
}

[TearDown]
public void TearDown()
{
_parser = null;
}

// Valid input test


[Test]
public void ParseHostName_ValidUrl_ReturnsHostName()
{
string url = "https://www.example.com/products";
string result = _parser.ParseHostName(url);
Assert.That(result, Is.EqualTo("www.example.com"));
}

// Invalid input test (blank or malformed)


[Test]
public void ParseHostName_InvalidUrl_ReturnsInvalidURL()
{
string url = "htp:/bad";
string result = _parser.ParseHostName(url);
Assert.That(result, Is.EqualTo("Invalid URL"));
}

// Empty string input


[Test]
public void ParseHostName_EmptyString_ReturnsInvalidURL()
{
string url = "";
string result = _parser.ParseHostName(url);
Assert.That(result, Is.EqualTo("Invalid URL"));
}

// Null string input


[Test]
public void ParseHostName_NullInput_ReturnsInvalidURL()
{
string url = null;
string result = _parser.ParseHostName(url);
Assert.That(result, Is.EqualTo("Invalid URL"));
}
}
}

4 NUNIT HANDS ON

AccountsManagerLib – Source Code


// Project: AccountsManagerLib

namespace AccountsManagerLib

public class AccountsManager

public string Login(string userId, string password)

if (string.IsNullOrWhiteSpace(userId) || string.IsNullOrWhiteSpace(password))

throw new ArgumentException("User ID or password cannot be empty");

if ((userId == "user_11" && password == "secret@user11") ||

(userId == "user_22" && password == "secret@user22"))

return $"Welcome {userId}!!!";

return "Invalid user id/password";


}

AccountsManagerLib.Tests – Test Class

// Project: AccountsManagerLib.Tests

using NUnit.Framework;

using AccountsManagerLib;

using System;

namespace AccountsManagerLib.Tests

[TestFixture]

public class AccountsManagerTests

private AccountsManager _accountsManager;

[SetUp]

public void Setup()

_accountsManager = new AccountsManager();

[Test]
public void Login_ValidCredentialsUser11_ReturnsWelcomeMessage()

string result = _accountsManager.Login("user_11", "secret@user11");

Assert.That(result, Is.EqualTo("Welcome user_11!!!"));

[Test]

public void Login_ValidCredentialsUser22_ReturnsWelcomeMessage()

string result = _accountsManager.Login("user_22", "secret@user22");

Assert.That(result, Is.EqualTo("Welcome user_22!!!"));

[Test]

public void Login_InvalidCredentials_ReturnsInvalidMessage()

string result = _accountsManager.Login("invalid_user", "wrongpass");

Assert.That(result, Is.EqualTo("Invalid user id/password"));

[Test]

public void Login_EmptyUserId_ThrowsArgumentException()

var ex = Assert.Throws<ArgumentException>(() => _accountsManager.Login("",


"somepass"));

Assert.That(ex.Message, Is.EqualTo("User ID or password cannot be empty"));


}

[Test]

public void Login_EmptyPassword_ThrowsArgumentException()

var ex = Assert.Throws<ArgumentException>(() =>


_accountsManager.Login("user_11", ""));

Assert.That(ex.Message, Is.EqualTo("User ID or password cannot be empty"));

[Test]

public void Login_NullUserId_ThrowsArgumentException()

var ex = Assert.Throws<ArgumentException>(() =>


_accountsManager.Login(null, "password"));

Assert.That(ex.Message, Is.EqualTo("User ID or password cannot be empty"));

[Test]

public void Login_NullPassword_ThrowsArgumentException()

var ex = Assert.Throws<ArgumentException>(() =>


_accountsManager.Login("user_22", null));

Assert.That(ex.Message, Is.EqualTo("User ID or password cannot be empty"));

}
}

5. NUNIT HANDS ON

CollectionsLib – Source Code


// Project: CollectionsLib
using System;
using System.Collections.Generic;
using System.Linq;

namespace CollectionsLib
{
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime JoinDate { get; set; }

public override bool Equals(object obj)


{
if (obj is Employee other)
return Id == other.Id;
return false;
}

public override int GetHashCode()


{
return Id.GetHashCode();
}
}

public class EmployeeRepository


{
public List<Employee> GetEmployees()
{
return new List<Employee>
{
new Employee { Id = 100, Name = "Thasleem", JoinDate = new
DateTime(2021, 01, 01) },
new Employee { Id = 101, Name = "Aisha", JoinDate = new DateTime(2023,
01, 01) },
new Employee { Id = 102, Name = "Karthik", JoinDate = new DateTime(2022,
05, 01) }
};
}

public List<Employee> GetEmployeesWhoJoinedInPreviousYears()


{
return new List<Employee>
{
new Employee { Id = 100, Name = "Thasleem", JoinDate = new
DateTime(2021, 01, 01) },
new Employee { Id = 102, Name = "Karthik", JoinDate = new DateTime(2022,
05, 01) },
new Employee { Id = 101, Name = "Aisha", JoinDate = new DateTime(2023,
01, 01) }
};
}
}
}

CollectionsLib.Tests – Unit Tests


// Project: CollectionsLib.Tests
using NUnit.Framework;
using CollectionsLib;
using System.Collections.Generic;
using System.Linq;

namespace CollectionsLib.Tests
{
[TestFixture]
public class EmployeeRepositoryTests
{
private EmployeeRepository _repo;
[SetUp]
public void Init()
{
_repo = new EmployeeRepository();
}

[Test]
public void GetEmployees_NoNullsInCollection_Passes()
{
var employees = _repo.GetEmployees();
Assert.That(employees, Is.All.Not.Null);
}

[Test]
public void GetEmployees_ContainsEmployeeWithId100_Passes()
{
var employees = _repo.GetEmployees();
Assert.That(employees.Any(e => e.Id == 100), Is.True);
}

[Test]
public void GetEmployees_UniqueEmployees_Passes()
{
var employees = _repo.GetEmployees();
var unique = employees.Distinct().ToList();
Assert.That(employees.Count, Is.EqualTo(unique.Count));
}

[Test]
public void GetEmployees_CompareWithPreviousYearEmployees_ClassicModel()
{
var current = _repo.GetEmployees();
var previous = _repo.GetEmployeesWhoJoinedInPreviousYears();

CollectionAssert.AreEquivalent(current, previous); // Classic Model


}

[Test]
public void
GetEmployees_CompareWithPreviousYearEmployees_ConstraintModel()
{
var current = _repo.GetEmployees();
var previous = _repo.GetEmployeesWhoJoinedInPreviousYears();

Assert.That(current, Is.EquivalentTo(previous)); // Constraint Model


}
}
}

6. NUNIT HANDS ON

FourSeasonsLib – Source Code


// Project: FourSeasonsLib
namespace FourSeasonsLib
{
public class SeasonFinder
{
public string GetSeason(string month)
{
month = month.Trim().ToLower();

if (month == "february" || month == "march")


return "Spring";

if (month == "april" || month == "may" || month == "june")


return "Summer";

if (month == "july" || month == "august")


return "Monsoon";

if (month == "september" || month == "october" || month == "november")


return "Autumn";

if (month == "december" || month == "january")


return "Winter";

return "Invalid month";


}
}
}

FourSeasonsLib.Tests – NUnit Test Project Using TestCaseSource


// Project: FourSeasonsLib.Tests
using NUnit.Framework;
using FourSeasonsLib;
using System.Collections;

namespace FourSeasonsLib.Tests
{
[TestFixture]
public class SeasonFinderTests
{
private SeasonFinder _finder;

[SetUp]
public void Init()
{
_finder = new SeasonFinder();
}

// Static data source


public static IEnumerable SeasonTestData
{
get
{
yield return new TestCaseData("February").Returns("Spring");
yield return new TestCaseData("March").Returns("Spring");
yield return new TestCaseData("April").Returns("Summer");
yield return new TestCaseData("May").Returns("Summer");
yield return new TestCaseData("June").Returns("Summer");
yield return new TestCaseData("July").Returns("Monsoon");
yield return new TestCaseData("August").Returns("Monsoon");
yield return new TestCaseData("September").Returns("Autumn");
yield return new TestCaseData("October").Returns("Autumn");
yield return new TestCaseData("November").Returns("Autumn");
yield return new TestCaseData("December").Returns("Winter");
yield return new TestCaseData("January").Returns("Winter");
yield return new TestCaseData("Hello").Returns("Invalid month");
yield return new TestCaseData("").Returns("Invalid month");
}
}

[Test, TestCaseSource(nameof(SeasonTestData))]
public string GetSeason_Month_ReturnsExpectedSeason(string month)
{
return _finder.GetSeason(month);
}
}
}

7. NUNIT HANDS ON

LeapYearCalculatorLib – Source Code


// Project: LeapYearCalculatorLib
namespace LeapYearCalculatorLib
{
public class LeapYearCalculator
{
public int IsLeapYear(int year)
{
if (year < 1753 || year > 9999)
return -1;

if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))


return 1;

return 0;
}
}
}

LeapYearCalculatorLib.Tests – Parameterized NUnit Tests


// Project: LeapYearCalculatorLib.Tests
using NUnit.Framework;
using LeapYearCalculatorLib;

namespace LeapYearCalculatorLib.Tests
{
[TestFixture]
public class LeapYearCalculatorTests
{
private LeapYearCalculator _calculator;

[SetUp]
public void Setup()
{
_calculator = new LeapYearCalculator();
}

[TestCase(2000, 1)] // Leap year divisible by 400


[TestCase(2024, 1)] // Leap year divisible by 4 not 100
[TestCase(1900, 0)] // Not a leap year (div by 100 but not 400)
[TestCase(2023, 0)] // Normal year
[TestCase(1752, -1)] // Invalid (before 1753)
[TestCase(10000, -1)] // Invalid (after 9999)
public void IsLeapYear_GivenYear_ReturnsExpectedResult(int year, int expected)
{
var result = _calculator.IsLeapYear(year);
Assert.That(result, Is.EqualTo(expected));
}
}
}

8. NUNIT HANDS ON

UserManagerLib – Source Code


// Project: UserManagerLib
namespace UserManagerLib
{
public class User
{
public string PANCardNo { get; set; }
}
public class UserManager
{
public string CreateUser(User user)
{
if (user == null || string.IsNullOrWhiteSpace(user.PANCardNo))
throw new NullReferenceException("PANCard number is required.");

if (user.PANCardNo.Length != 10)
throw new FormatException("PANCard number must be exactly 10 characters
long.");

return "User created successfully.";


}
}
}

UserManagerLib.Tests – NUnit Unit Tests


// Project: UserManagerLib.Tests
using NUnit.Framework;
using UserManagerLib;
using System;

namespace UserManagerLib.Tests
{
[TestFixture]
public class UserManagerTests
{
private UserManager _userManager;

[SetUp]
public void Setup()
{
_userManager = new UserManager();
}

[Test]
public void CreateUser_ValidPANCard_ReturnsSuccessMessage()
{
var user = new User { PANCardNo = "ABCDE1234Z" };

var result = _userManager.CreateUser(user);

Assert.That(result, Is.EqualTo("User created successfully."));


}

[Test]
public void CreateUser_EmptyPANCard_ThrowsNullReferenceException()
{
var user = new User { PANCardNo = "" };

var ex = Assert.Throws<NullReferenceException>(() =>


_userManager.CreateUser(user));
Assert.That(ex.Message, Is.EqualTo("PANCard number is required."));
}

[Test]
public void CreateUser_NullUser_ThrowsNullReferenceException()
{
User user = null;

var ex = Assert.Throws<NullReferenceException>(() =>


_userManager.CreateUser(user));
Assert.That(ex.Message, Is.EqualTo("PANCard number is required."));
}

[TestCase("ABC123")] // Too short


[TestCase("ABCDE123456")] // Too long
public void CreateUser_InvalidPANLength_ThrowsFormatException(string pan)
{
var user = new User { PANCardNo = pan };

var ex = Assert.Throws<FormatException>(() =>


_userManager.CreateUser(user));
Assert.That(ex.Message, Is.EqualTo("PANCard number must be exactly 10
characters long."));
}
}
}
9. NUNIT HANDS ON

ConverterLib – Source Code


// Project: ConverterLib
namespace ConverterLib
{
public interface IDollarToEuroExchangeRateFeed
{
double GetActualUSDToEuroExchangeRate();
}

public class Converter


{
private readonly IDollarToEuroExchangeRateFeed _rateFeed;

public Converter(IDollarToEuroExchangeRateFeed rateFeed)


{
_rateFeed = rateFeed;
}

public double USDToEuro(double amountInUSD)


{
double rate = _rateFeed.GetActualUSDToEuroExchangeRate();
return amountInUSD * rate;
}
}
}

ConverterLib.Tests – NUnit + Moq Based Test


// Project: ConverterLib.Tests
using NUnit.Framework;
using Moq;
using ConverterLib;

namespace ConverterLib.Tests
{
[TestFixture]
public class ConverterTests
{
private Mock<IDollarToEuroExchangeRateFeed> _mockRateFeed;
private Converter _converter;

[SetUp]
public void Setup()
{
_mockRateFeed = new Mock<IDollarToEuroExchangeRateFeed>();
}

[Test]
public void USDToEuro_WithFixedRate_ReturnsCorrectConversion()
{
_mockRateFeed.Setup(x =>
x.GetActualUSDToEuroExchangeRate()).Returns(0.85);

_converter = new Converter(_mockRateFeed.Object);

double result = _converter.USDToEuro(100);

Assert.That(result, Is.EqualTo(85.0));
}

[Test]
public void USDToEuro_ZeroInput_ReturnsZero()
{
_mockRateFeed.Setup(x =>
x.GetActualUSDToEuroExchangeRate()).Returns(0.85);

_converter = new Converter(_mockRateFeed.Object);

double result = _converter.USDToEuro(0);

Assert.That(result, Is.EqualTo(0));
}

[Test]
public void USDToEuro_NegativeInput_ReturnsNegativeEuro()
{
_mockRateFeed.Setup(x =>
x.GetActualUSDToEuroExchangeRate()).Returns(0.85);

_converter = new Converter(_mockRateFeed.Object);

double result = _converter.USDToEuro(-50);

Assert.That(result, Is.EqualTo(-42.5));
}
}
}

You might also like