C# Unit Testing with Moq: Verifying Method Calls and Exceptions
- Published on
- • 2 mins read•--- views
Moq - is useful framework that allows to simulate any functionality provided by object being tested. For example, you need to check is any method called in test scenario, so moq let you to do that. Just mock testable method, run scenario and detect is it being called at the end of test scenario. Official documentation and examples allowed here - Quickstart. And also i want to show one some helpful features for me. Read below. ### Check did method was called inside object.
For example, you have logger interface and it's implementation:
using System;
namespace ...
{
public interface IIntegrationLog
{
void Error(string msg);
void ExecuteWithLogging(Action action);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
...
namespace ...
{
public class IntegrationLog: IIntegrationLog
{
...
public virtual void Error(string msg)
{
Log(Error, msg);
}
public void ExecuteWithLogging(Action action)
{
try
{
action.Invoke();
}
catch (Exception ex)
{
this.Error(ex.Message);
}
}
}
}
Major task is check did method Error was called inside and if it was, how mush times? So, i wrote test class for it:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace ...
{
[TestClass]
public class IntegrationLogTests
{
private Mock<IntegrationLog> _integrationLog;
// mocking testable object:
// implementing method Error() taking string as argument
[TestInitialize]
public void TestInitialize()
{
this._integrationLog = new Mock<IntegrationLog>();
this._integrationLog.Setup(m => m.Error(It.IsAny<string>()));
}
// caller method not twrows any exceptions
// so, => Error not called
[TestMethod]
public void ExecuteWithLogging_ExecuteWithLogging_Successed()
{
this._integrationLog.Object.ExecuteWithLogging(() =>
{
return;
});
this._integrationLog.Verify(m => m.Error(error), Times.Never());
}
// caller throws 1 exception
[TestMethod]
public void ExecuteWithLogging_ExecuteWithLogging_ExceptionCaught()
{
this._integrationLog.Object.ExecuteWithLogging(() =>
{
throw new System.Exception(error);
});
this._integrationLog.Verify(m => m.Error(error), Times.Once());
}
// caller throws 2 exception
[TestMethod]
public void ExecuteWithLogging_ExecuteWithLogging_ExecuteWithLogging2Level()
{
this._integrationLog.Object.ExecuteWithLogging(() =>
{
for (int i = 0; i < 2; i++)
{
this._integrationLog.Object.ExecuteWithLogging(() =>
{
throw new System.Exception(error);
});
}
});
this._integrationLog.Verify(m => m.Error(error), Times.Exactly(2));
}
// caller throws 3 exception
[TestMethod]
public void ExecuteWithLogging_ExecuteWithLogging_ExecuteWithLogging3Level()
{
this._integrationLog.Object.ExecuteWithLogging(() =>
{
for (int i = 0; i < 2; i++)
{
this._integrationLog.Object.ExecuteWithLogging(() =>
{
throw new System.Exception(error);
});
}
throw new System.Exception(error);
});
this._integrationLog.Verify(m => m.Error(error), Times.Exactly(3));
}
}
}
Table of Contents
Related
Posts
Project Structure and Testing in .NET Core 6 vs .NET Core 5: Unit Tests, GraphQL, and Test Server Fixtures
A practical comparison of .NET Core 5 and 6 project structures, with real-world examples for unit testing, GraphQL integration, and test server fixture setup.
C# FluentValidation: Custom Validators with Dynamic Error Messages
How to create custom validators in FluentValidation for C#, including dynamic error messages with parameter bindings and extension methods.
Environment Variables and Secrets in .NET Core: Best Practices
Learn how to securely manage environment variables and secrets in .NET Core, with practical configuration tips and code examples.
Open for contract collaboration
I am available for contract-based collaboration. If you have an interesting project idea, schedule a call via Calendly.
Schedule a 30-min call