Юнит-тестирование C# с Moq: проверка вызовов методов и исключений
- Опубликовано
- • 2 мин чтения•--- просмотров
Moq — полезный фреймворк, который позволяет симулировать любую функциональность объекта, который тестируется. Например, тебе нужно проверить, был ли вызван какой-то метод в тестовом сценарии — moq позволяет это сделать. Просто замокай тестируемый метод, запусти сценарий и в конце проверь, был ли он вызван. Официальная документация и примеры доступны здесь — Quickstart. А ещё хочу показать пару полезных для меня фич. Читай ниже. ### Проверка, был ли вызван метод внутри объекта.
Например, у тебя есть интерфейс логгера и его реализация:
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);
}
}
}
}
Основная задача — проверить, был ли вызван метод Error внутри, и если да, то сколько раз? Поэтому я написал для этого тестовый класс:
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));
}
}
}
Содержание
Открыт для работы по контракту
Я доступен для работы по контракту. Если у вас есть интересная идея проекта — запишитесь на звонок через Calendly.
Записаться на 30-минутный звонок