При написании примера модульного теста для проверки выброшенного исключения мы попытались использовать ниже оба метода с помощью xUnit.
Ниже приведен код
public class Me : Entity, IAggregateRoot
{
public string Name {get; }
private List<Friend> friends;
public IReadonlyCollection<Friend> Friends => friends;
public Me(string name)
{
Name = name;
friends = new List<Friend>();
}
public void AddFriend(Friend friend)
{
if (friend.Type != "UnKnown")
friend.Add(friend);
else
throw new Exception("Cannot add a unknown friend.");
}
}
public class Friend
{
public string Name {get; }
public string Type {get; }
public Friend(string name, string type)
{
Name = name;
Type = type;
}
}
using System;
using MediatR;
using System.Collections.Generic;
public abstract class Entity
{
int? _requestedHashCode;
int _Id;
public virtual int Id
{
get
{
return _Id;
}
protected set
{
_Id = value;
}
}
private List<INotification> _domainEvents;
public IReadOnlyCollection<INotification> DomainEvents => _ domainEvents?.AsReadOnly();
public void AddDomainEvent(INotification eventItem)
{
_domainEvents = _domainEvents ?? new List<INotification>();
_domainEvents.Add(eventItem);
}
public void RemoveDomainEvent(INotification eventItem)
{
_domainEvents?.Remove(eventItem);
}
public void ClearDomainEvents()
{
_domainEvents?.Clear();
}
public bool IsTransient()
{
return this.Id == default(Int32);
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is Entity))
return false;
if (Object.ReferenceEquals(this, obj))
return true;
if (this.GetType() != obj.GetType())
return false;
Entity item = (Entity)obj;
if (item.IsTransient() || this.IsTransient())
return false;
else
return item.Id == this.Id;
}
public override int GetHashCode()
{
if (!IsTransient())
{
if (!_requestedHashCode.HasValue)
_requestedHashCode = this.Id.GetHashCode() ^ 31;
return _requestedHashCode.Value;
}
else
return base.GetHashCode();
}
public static bool operator ==(Entity left, Entity right)
{
if (Object.Equals(left, null))
return (Object.Equals(right, null)) ? true : false;
else
return left.Equals(right);
}
public static bool operator !=(Entity left, Entity right)
{
return !(left == right);
}
}
public interface IAggregateRoot
{}//its empty
Тестовый пример 1: Использование Assert.Throws
[Fact]
public void add_friend_business_rule_validation_throws_exception1()
{
var me = new Me("mady");
var friend = new Friend("johnDoe","UnKnown");
Assert.Throws<Exception>(() => me.AddFriend(friend));
}
Тестовый пример 2: использование Record.Exception
[Fact]
public void add_friend_business_rule_validation_throws_exception()
{
var me = new Me("mady");
var friend = new Friend("johnDoe","UnKnown");
var ex = Record.Exception(() => me.AddFriend(friend));
Assert.NotNull(ex);
Assert.IsType<Exception>(ex);
}
Я хотел бы написать модульный тестовый пример для проверки исключения для предоставленного кода. Я ожидаю, что код должен выдавать исключение при сбое проверки при попытке добавить объект в коллекцию.
Проблема: Тестовые случаи здесь не провалены и не пройдены. Выполнение останавливается на следующей строке.
throw new Exception("Cannot add a unknown friend.");
Это произойдет, если у вас нет блока try catch для его перехвата. Я ожидаю, что xUnit Assert.Throws & Record.Exception поймает исключение, но это не так.
Примечание: Предоставленный код очень близок к фактическому коду, с другими именами объектов, которые упрощены за счет удаления ненужного кода.
Я видел следующую документацию
Обновлено:Поведение xUnit Assert.Throws & Record.Exception соответствует ожиданиям, пока я запускаю тесты.
Проблема связана с отладочными тестами.
Как уже упоминалось, тестовые случаи не были провалены или пройдены. Всякий раз, когда какая-либо строка кода генерирует исключение, ближайший блок catch должен перехватывать исключение. У меня есть аналогичные ожидания от xUnit Assert.Throws & Record.Exception, основанные на документации и пользовательском опыте. Однако это не так во время отладки теста.
Альтернативный и хорошо известный подход для демонстрации проблемы и ожидаемого поведения.
[Fact]
public void add_friend_business_rule_validation_throws_exception1()
{
var me = new Me("mady");
var friend = new Friend("johnDoe","UnKnown");
Exception expectedException = null;
try
{
me.AddFriend(friend); //exception thrown block
}
catch(Exception ex)//exception catched - control not stopped
{
expectedException = ex;
}
Assert.NotNull(expectedException);
Assert.IsType<Exception>(expectedException);
}
Да это так. Асинхронная задача не используется.
Я только что протестировал первый сценарий, используя предоставленный код, и он прошел, как и ожидалось. Пришлось исправить несколько незначительных синтаксических ошибок, но при выполнении теста он ведет себя так, как ожидалось.
Я обновил класс Me фактическим базовым классом.
Это может быть проблема XY. Предоставьте минимальный воспроизводимый пример, разъясняющий вашу конкретную проблему, или добавьте дополнительные сведения, чтобы выделить именно то, что вам нужно. В том виде, в котором он сейчас написан, трудно точно сказать, о чем вы спрашиваете.
Как выглядит настоящий AddFriend. Скорее всего, вы либо утверждаете, либо возвращаете неправильный тип исключения.
Я обновил описание и предоставил более подробную информацию, пожалуйста, проверьте.
Запустил его снова с дополнительным кодом, и он работает, как и ожидалось. Я предлагаю вам попробовать создать новый проект с кодом и посмотреть, сохраняется ли проблема. В настоящее время я не могу воспроизвести проблему.





Поведение xUnit Assert.Throws & Record.Exception соответствует ожиданиям, пока я запускаю тесты.
Проблема связана с отладочными тестами.
Я смог отладить тест, перешагнув через строку с выброшенным исключением. После того, как вы увидите, что элемент управления остановился на линии, нажмите F8 или F5, чтобы продолжить, и тест будет выполнен.
throw new Exception("Cannot add a unknown friend.");
Является ли показанный пример кода точным представлением фактического кода? Используете ли вы асинхронную задачу где-либо в реальном коде?