xUnit Assert.Throws和Record.Exception不会捕获异常

问题描述 投票:0回答:1

在编写单元测试用例来测试抛出异常时,尝试使用xUnit在下面两种方法中使用

  1. Assert.Throws(动作)
  2. Record.Exception(动作)

以下是代码

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.");

当你没有尝试catch块来捕获它时会发生这种情况。我期待xUnit Assert.Throws&Record.Exception将捕获异常,但事实并非如此。

注意:提供的代码非常接近实际代码,通过删除不必要的代码,实体名称不同并简化。

我见过以下文档

  1. xUnit-Record.Exception Documentation
  2. Assert an Exception using XUnit- Stackoverflow question

编辑: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);
}
c# unit-testing asp.net-core-2.0 xunit.net mediatr
1个回答
0
投票

在运行测试时,xUnit Assert.Throws&Record.Exception行为与预期一致。

问题在于调试测试。

我可以通过从异常抛出的行中跳过来调试测试。当您看到控制器停在该线路上后,按F8或F5继续,将执行测试。

throw new Exception("Cannot add a unknown friend.");
© www.soinside.com 2019 - 2024. All rights reserved.