XUnit Assert.Throws и Record.Exception не перехватывает исключение

При написании примера модульного теста для проверки выброшенного исключения мы попытались использовать ниже оба метода с помощью xUnit.

  1. Assert.Throws(действие)
  2. Запись.Исключение(действие)

Ниже приведен код

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 поймает исключение, но это не так.

Примечание: Предоставленный код очень близок к фактическому коду, с другими именами объектов, которые упрощены за счет удаления ненужного кода.

Я видел следующую документацию

  1. xUnit-Record.Exception Документация
  2. Подтвердите исключение, используя вопрос XUnit- Stackoverflow

Обновлено:Поведение 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);
}

Является ли показанный пример кода точным представлением фактического кода? Используете ли вы асинхронную задачу где-либо в реальном коде?

Nkosi 03.03.2019 21:51

Да это так. Асинхронная задача не используется.

Mady 03.03.2019 22:06

Я только что протестировал первый сценарий, используя предоставленный код, и он прошел, как и ожидалось. Пришлось исправить несколько незначительных синтаксических ошибок, но при выполнении теста он ведет себя так, как ожидалось.

Nkosi 03.03.2019 22:10

Я обновил класс Me фактическим базовым классом.

Mady 03.03.2019 22:28

Это может быть проблема XY. Предоставьте минимальный воспроизводимый пример, разъясняющий вашу конкретную проблему, или добавьте дополнительные сведения, чтобы выделить именно то, что вам нужно. В том виде, в котором он сейчас написан, трудно точно сказать, о чем вы спрашиваете.

Nkosi 03.03.2019 22:35

Как выглядит настоящий AddFriend. Скорее всего, вы либо утверждаете, либо возвращаете неправильный тип исключения.

Nkosi 03.03.2019 22:36

Я обновил описание и предоставил более подробную информацию, пожалуйста, проверьте.

Mady 03.03.2019 23:13

Запустил его снова с дополнительным кодом, и он работает, как и ожидалось. Я предлагаю вам попробовать создать новый проект с кодом и посмотреть, сохраняется ли проблема. В настоящее время я не могу воспроизвести проблему.

Nkosi 04.03.2019 00:28
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
3 472
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поведение xUnit Assert.Throws & Record.Exception соответствует ожиданиям, пока я запускаю тесты.

Проблема связана с отладочными тестами.

Я смог отладить тест, перешагнув через строку с выброшенным исключением. После того, как вы увидите, что элемент управления остановился на линии, нажмите F8 или F5, чтобы продолжить, и тест будет выполнен.

throw new Exception("Cannot add a unknown friend.");

Другие вопросы по теме