Showing posts with label UnitTest. Show all posts
Showing posts with label UnitTest. Show all posts

Thursday, 24 October 2024

Unit Test Coding

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.

  1. Assert.AreEqual(object, object)
  2. Assert.IsTrue(bool), Assert.IsFalse(bool)
  3. Assert.IsNull(object), Assert.IsNotNull(object)
  4. 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()
          {
// Arrange
              var mockedIdentity = new Moq.Mock<IIdentity>();
              mockedIdentity.Setup(x => x.Name).Returns("notanadmin");
 
// Act
              var result = ApplicationUtils.IsUserAManager(mockedIdentity.Object);
 
// Assert
              Assert.IsFalse(result);
          }
 
          [TestMethod]
          public void IsUserAManagerTestIsAdminReturnsTrue()
          {
// Arrange
              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:

  1. Create a wrapper class and use dependency injection
  2. Use a static Func property
  3. 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);
      }
  }

xUnit, NUnit, and MSTest are the three primary testing frameworks in .NET.


Continue Reading →

Saturday, 26 September 2020

Unit Testing in C#

What is Test-Driven Development (TDD)?

Test-Driven Development (TDD) is a software development process in which tests are written before the actual code. The cycle typically involves:

  1. Writing a failing test for a new feature.
  2. Writing the minimum amount of code necessary to pass the test.
  3. Refactoring the code while keeping the tests passing.

This approach helps ensure that the code meets its requirements and is maintainable. 

What do you mean by a Unit test ?

In the software development process Unit Tests basically test individual parts of code (mostly methods) and make it work as expected by programmer. A Unit Test is a code written by any programmer which test small pieces of functionality of big programs.

Why do we need Unit test?

One of the most valuable benefits of using Unit Tests for your development is that it may give you positive confidence that your code will work as you have expected it to work in your development process. 

One of the fundamental principles of adopting unit testing is to follow a TDD (Test Driven Development) aproach where we have to write tests case first, and then write the simple code that will make the test pass.

We can use MS Unit tests, nUnit for creating Test methods. Below is an example of MS Unit test code.

Code to be tested

public class BasicMaths {  
    public double Add(double num1, double num2) {  
        return num1 + num2;  
    }   
} 

Test method for above code testing

[TestClass]  
public class UnitTest1 {  
    [TestMethod]  
    public void Test_AddMethod() {  
            BasicMaths bm = new BasicMaths();  
            double res = bm.Add(10, 10);  
            Assert.AreEqual(res, 20);  
        }  
}  

What are some common assertions used in unit tests?

Common assertions include:

  • Assert.AreEqual(expected, actual): Checks if two values are equal.
  • Assert.IsTrue(condition): Checks if a condition is true.
  • Assert.IsFalse(condition): Checks if a condition is false.
  • Assert.IsNull(object): Checks if an object is null.
  • Assert.IsNotNull(object): Checks if an object is not null.

How do you handle exceptions in unit tests?

You can handle exceptions in unit tests using the Assert.Throws method in NUnit or Assert.Throws<T> in xUnit. This checks if the expected exception is thrown during the execution of the code.

  [Test]
  public void Divide_ByZero_ThrowsException()
  {
      var calculator = new Calculator();
      Assert.Throws<DivideByZeroException>(() => calculator.Divide(5, 0));
  }

How can you improve the performance of unit tests?

To improve the performance of unit tests:

  • Minimize dependencies by mocking external resources.
  • Use parallel test execution where supported by the testing framework.
  • Avoid heavy initialization code in test setups.
  • Focus on testing only relevant parts of the application to reduce test complexity.
What is the Arrange-Act-Assert pattern, and how is it used in unit testing?
The Arrange-Act-Assert (AAA) pattern is a commonly used pattern in unit testing to structure test code. It involves three steps:

Arrange: In this step, the test environment is set up, including creating necessary objects, initializing variables, and mocking dependencies.
Act: In this step, the actual behavior being tested is executed. This typically involves calling a method or function with specific inputs.
Assert: In this step, the output of the behavior being tested is checked to ensure it meets the expected criteria. This can include checking return values, throwing expected exceptions, or verifying side effects.

By following the AAA pattern, unit tests become easier to read and understand, and it helps ensure that the tests are focused on one specific aspect of the code.

What is Mocking?

Mocking is a technique used in unit testing to simulate the behavior of external dependencies or objects that are difficult or impractical to use in a unit test. It involves creating mock objects that mimic the behavior of the real objects and can be controlled by the test code. Mock objects can be used to test the behavior of a unit of code in isolation, without the need for the real objects or dependencies. 

In short, mocking is creating objects that simulate the behavior of real objects.

Moq Framework

Moq is an open-source framework which can be found on GitHub. When start using Moq make sure you always install the very latest version.

When using Moq or any other mocking framework keep following restrictions in mind. You can not mock:

  1. Static class/methods.
  2. Extensions Methods.
  3. Non-virtual methods (except there is an interface).
How to Use Moq to Ease Unit Testing https://dzone.com/

What is code coverage, and why is it important in unit testing?
Code coverage is a critical metric in software testing that measures the percentage of code that has been executed by a test suite. It is important in unit testing because it helps to ensure that all parts of the code are being tested and that potential errors or bugs have been identified. By measuring code coverage, developers can identify areas of code that are not being tested and can adjust their test suite accordingly.




Continue Reading →

Topics

ADFS (1) ADO .Net (1) Ajax (1) Angular (47) Angular Js (15) ASP .Net (14) Authentication (4) Azure (3) Breeze.js (1) C# (55) CD (1) CI (2) CloudComputing (2) Coding (10) CQRS (1) CSS (2) Design_Pattern (7) DevOps (4) DI (3) Dotnet (10) DotnetCore (20) Entity Framework (5) ExpressJS (4) Html (4) IIS (1) Javascript (17) Jquery (8) jwtToken (4) Lamda (3) Linq (10) microservice (4) Mongodb (1) MVC (46) NodeJS (8) React (10) SDLC (1) Sql Server (32) SSIS (3) SSO (1) TypeScript (3) UI (1) UnitTest (2) WCF (14) Web Api (16) Web Service (1) XMl (1)

Dotnet Guru Archives