What is Assert method?
Assert is a static class which contains some methods to help you make checks in your test code. The methods check your condition and if the condition fails, it’ll also make the test fail with a nice message to it. These methods are pretty straightforward so I will just mention a couple of them, without explaining them.
- Assert.AreEqual(object, object)
- Assert.IsTrue(bool), Assert.IsFalse(bool)
- Assert.IsNull(object), Assert.IsNotNull(object)
- Assert.ThrowsException(Action) — useful if you expect an excetion to be thrown
1: Unit Testing a Static Method of a Static Class using MOQ
Below function will take identity as a parameter and check if user is Manager.
public static class ApplicationUtils
{
public static bool IsUserAManager(IIdentity identity)
{
if (identity == null)
throw new NullReferenceException("identity");
return identity.Name == "AdminUser";
}
}
And Your Test Class using Moq.
using DemoClassLib;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Security.Principal;
namespace DemoUnitTestProject
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void IsUserAManagerTestIsAdminReturnsFalse()
{
var mockedIdentity = new Moq.Mock<IIdentity>();
mockedIdentity.Setup(x => x.Name).Returns("notanadmin");
var result = ApplicationUtils.IsUserAManager(mockedIdentity.Object);
Assert.IsFalse(result);
}
[TestMethod]
public void IsUserAManagerTestIsAdminReturnsTrue()
{
var mockedIdentity = new Moq.Mock<IIdentity>();
mockedIdentity.Setup(x => x.Name).Returns("AdminUser");
// Act
var result = ApplicationUtils.IsUserAManager(mockedIdentity.Object);
// Assert
Assert.IsTrue(result);
}
}
}
Explanation
Test Class and Methods: Each test method is annotated with the [TestMethod] attribute. The class is marked with [TestClass].
Arrange-Act-Assert Pattern:
Arrange: Set up the necessary variables.
Act: Call the method under test.
Assert: Verify the result using assertions.
Multiple Test Cases: You can create multiple test methods to cover various scenarios and edge cases.
2: Amazing Ways to Unit Test Code That Calls Static Method in C#
Static methods can often seem like an excellent way to achieve reusability.
Write them once and call them whenever you want. The problem, however, arises when you need to test the C# code that calls a static method. It’s not straightforward to mock the static method for testing purposes.
There are three ways to test the code that calls static methods:
- Create a wrapper class and use dependency injection
- Use a static Func property
- Use the Extract and override call
Follow
link here for more...
3: Create a Unit test for below service function which is calling repository method.
public interface IRepository
{
string GetData(int id);
}
public class MyService
{
private readonly IRepository _repository;
public MyService(IRepository repository)
{
_repository = repository;
}
public string GetServiceData(int id)
{
return _repository.GetData(id);
}
}
Now, create a test method in test class:
[TestMethod]
public void GetServiceData_ReturnsExpectedData()
{
// Arrange
var mockRepo = new Mock<IRepository>();
mockRepo.Setup(repo => repo.GetData(1)).Returns("Test Data");
var service = new MyService(mockRepo.Object);
// Act
var result = service.GetServiceData(1);
// Assert
Assert.AreEqual("Test Data", result);
}
Definitions for the following examples:
public interface IEmployee
{
EmploymentHistory EmploymentHistory { get; set; }
string Name { get; set; }
int Id { get; set; }
bool IsEmployeeExist(string value);
bool DoSomething(int number, string value);
Task<bool> DoSomethingAsync();
string DoSomethingStringy(string value);
bool IsEmployeeExist(string value, out string outputValue);
bool Submit(ref EmploymentHistory bar);
int GetEmployeeCount();
bool Add(int value);
}
public class EmploymentHistory
{
public virtual Employer Employer { get; set; }
public virtual bool Submit() { return false; }
}
public class Employer
{
public virtual string Name { get; set; }
}
You can setup the behavior of any of a mock's overridable methods using Setup, combined with e.g. Returns (so they return a value) or Throws (so they throw an exception):
var mock = new Mock<IEmployee>();
mock.Setup(emp => emp.IsEmployeeExist("suraj")).Returns(false);
// out arguments
var outString = "welcome";
// IsEmployeeExist will return true, and the out argument will return "welcome",
// lazy evaluated
mock.Setup(emp => emp.IsEmployeeExist("suraj", out outString)).Returns(true);
// access invocation arguments when returning a value
mock.Setup(x => x.DoSomethingStringy(It.IsAny<string>()))
.Returns((string s) => s.ToLower());
// Multiple parameters overloads available
// throwing when invoked with specific parameters
mock.Setup(emp => emp.IsEmployeeExist("12ka4")).Throws<InvalidOperationException>();
mock.Setup(emp => emp.IsEmployeeExist("")).Throws(new ArgumentException("command"));
// lazy evaluating return value
var count = 1;
mock.Setup(emp => emp.GetEmployeeCount()).Returns(() => count);
// async methods (see below for more about async):
mock.Setup(emp => emp.DoSomethingAsync().Result).Returns(true);
// ref arguments
var instance = new EmploymentHistory();
// Only matches if the ref argument to the invocation is the same instance
mock.Setup(emp => emp.Submit(ref instance)).Returns(true);
It.IsAny<T> is checking that the parameter is of type T, it can be any instance of type T. It's basically saying, I don't care what you pass in here as long as it is type of T.
4: Write a Unit test for following EntityClass.
public interface IEntityRepository
{
string GetName(int id);
}
public class EntityRepository:IEntityRepository
{
public string GetName(int id)
{
// Code to connect to DB and get name based on Id
return "NameFromDb";
}
}
public class EntityClass
{
private IEntityRepository _entityRepository;
public EntityClass(IEntityRepository entityRepository)
{
this._entityRepository = entityRepository;
}
public string Name { get; set; }
public string GetNameWithPrefix(int id)
{
string name = string.Empty;
if (id > 0)
{
name = this._entityRepository.GetName(id);
}
return "Mr. " + name;
}
}
Unit test methods here.
Example of mock vs stub using Moq. I have used Verify but you can use VerifyAll as well.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
...
[TestClass]
public class UnitTest1
{
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method calls
/// Repository GetName method once when Id is greater than Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_GetNameCalledOnce()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
mockEntityRepository.Verify(
m => m.GetName(It.IsAny<int>()), Times.Once);
}
/// <summary>
/// Test using Mock to Verify that GetNameWithPrefix method
/// doesn't calls Repository GetName method when Id is Zero
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsZero_GetNameNeverCalled()
{
// Arrange
var mockEntityRepository = new Mock<IEntityRepository>();
mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
var entity = new EntityClass(mockEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(0);
// Assert
mockEntityRepository.Verify(
m => m.GetName(It.IsAny<int>()), Times.Never);
}
/// <summary>
/// Test using Stub to Verify that GetNameWithPrefix method
/// returns Name with a Prefix
/// </summary>
[TestMethod]
public void GetNameWithPrefix_IdIsTwelve_ReturnsNameWithPrefix()
{
// Arrange
var stubEntityRepository = new Mock<IEntityRepository>();
stubEntityRepository.Setup(m => m.GetName(It.IsAny<int>()))
.Returns("Stub");
const string EXPECTED_NAME_WITH_PREFIX = "Mr. Stub";
var entity = new EntityClass(stubEntityRepository.Object);
// Act
var name = entity.GetNameWithPrefix(12);
// Assert
Assert.AreEqual(EXPECTED_NAME_WITH_PREFIX, name);
}
}