在编写单元测试用例以测试抛出的异常时,尝试使用以下两种方法使用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.");这将发生在您没有尝试捕获块来捕获它时。我预计xUnit Assert.Throws & Record.Exception会捕捉到异常,但事实并非如此。
注意:提供的代码与实际代码非常接近,实体名称是不同的,通过删除不必要的代码来简化。
我看过以下文档
编辑:在我运行Tests.时, 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);
}发布于 2019-03-04 18:50:50
运行测试时, xUnit Assert.Throws & Record.Exception行为与预期相同。
问题与调试测试有关.
我能够通过从异常抛出的行中跳转来调试测试。在看到在行处停止的控件后,按F8或F5继续,然后执行测试。
throw new Exception("Cannot add a unknown friend.");https://stackoverflow.com/questions/54973512
复制相似问题