单元测试中的对象比较

发布于 2024-08-20 05:26:35 字数 298 浏览 3 评论 0原文

我的单元测试中有两个对象,实际对象和预期对象。对象方法上的所有属性都完全相同,如果我运行以下测试:

Assert.AreEqual( expectedObject.Property1, actualObject.Property1);

结果按预期通过。但是,当我尝试运行以下测试时,它失败了:

Assert.AreEqual (expectedObject, actualObject);

我缺少什么?两个对象不能比较吗?我是否必须检查每个属性?

I have two objects in my unit test, the actual and expected object. All properties on the object method are the exact same and if I run the following test:

Assert.AreEqual( expectedObject.Property1, actualObject.Property1);

the result passes as expected. However, when I try to run the following test it fails:

Assert.AreEqual (expectedObject, actualObject);

What am I missing? Can two objects not be compared and do I have to do a check on each property?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

很酷不放纵 2024-08-27 05:26:35

您需要为您的对象重写EqualsAssert 使用Object.Equals。默认情况下,引用类型对象上的Object.Equals 会执行引用比较。也就是说,引用类型的两个实例当且仅当它们引用同一个对象时才相等。您想要覆盖此设置,以便执行值比较而不是执行引用比较。这是一篇关于该主题的非常好的 MSDN 文章。请注意,您还需要重写GetHashCode。请参阅 MSDN 了解指南。这是一个简单的例子:

之前:

class Test {
    public int Value { get; set; }
}

Test first = new Test { Value = 17 };
Test second = new Test { Value = 17 };
Console.WriteLine(first.Equals(second)); // false

之后:

class Test {
    public int Value { get; set; }
    public override bool Equals(object obj) {
        Test other = obj as Test;
        if(other == null) {
            return false; 
        }
        return this.Value == other.Value;
    }
    public override int GetHashCode() { 
        return this.Value.GetHashCode();
    }
}

Test first = new Test { Value = 17 };
Test second = new Test { Value = 17 };
Console.WriteLine(first.Equals(second)); // true

You need to override Equals for your object. Assert uses Object.Equals. By default, Object.Equals on objects of reference type performs a reference comparison. That is, two instances of a reference type are equal if and only if they refer to the same object. You want to override this so that instead of a reference comparison being performed a value comparison is performed. Here is a very nice MSDN article on the subject. Note that you also need to override GetHashCode. See MSDN fo the guidelines. Here is a simple example:

Before:

class Test {
    public int Value { get; set; }
}

Test first = new Test { Value = 17 };
Test second = new Test { Value = 17 };
Console.WriteLine(first.Equals(second)); // false

After:

class Test {
    public int Value { get; set; }
    public override bool Equals(object obj) {
        Test other = obj as Test;
        if(other == null) {
            return false; 
        }
        return this.Value == other.Value;
    }
    public override int GetHashCode() { 
        return this.Value.GetHashCode();
    }
}

Test first = new Test { Value = 17 };
Test second = new Test { Value = 17 };
Console.WriteLine(first.Equals(second)); // true
悲喜皆因你 2024-08-27 05:26:35

第二个断言语句实际上比较对象的引用,而不是内容。由于 AreEqual 方法的参数是对象类型,因此没有太多关于单元测试框架应如何比较这些参数的信息。

编辑:检查这个问题:比较 NUnit 中两个对象之间的相等性

The second assert statement actually compares the references of the objects, not the content. Since the parameters of the AreEqual method are of type objects, there's not much information on how the unit test framework should compare these.

EDIT: check this question: Compare equality between two objects in NUnit

回忆凄美了谁 2024-08-27 05:26:35

除非您已将“=”符号重载到对象中,否则您不能使用它。在您的对象类中,您需要执行以下操作:


public override bool Equals(object obj)
{
   if(obj == null)
      return false;
   return (this.Property1 == obj.Property1 && 
          this.Property2 == obj.Property2);
}

如果您不这样做,那么您只是简单地比较对象引用。

You could not use the '= ' sign unless you have overloaded it to your object. In your object class you need to do something like:


public override bool Equals(object obj)
{
   if(obj == null)
      return false;
   return (this.Property1 == obj.Property1 && 
          this.Property2 == obj.Property2);
}

If you don't do this, then you are just simply comparing the object references.

筱果果 2024-08-27 05:26:35

这是真实的。两个对象是否相等完全取决于其Equals方法的实现。有时使用 Equal 方法,重写 GetHashCode 实现也是不错的选择。如果不重写,则将与 Equal 方法的评估一起考虑默认的虚拟实现(Object 类)。为了使对象被视为相等,它们的哈希码应该相同。

但是对于单元测试,我建议不要严重依赖 Equal 方法的实现。无论您想要确定什么属性,请自行比较对象的这些属性,因为 Equal 方法可能是自定义实现,因此最终可能会包含错误。因此,更好地信任系统定义的类的 Equal 方法来进行单元测试。

This is true. Whether the two objects are equal or not are entirely depends on its Equals method's implementation. Sometime with the Equal method, it is also good to override the GetHashCode implementation. If it is not override, the default virtual implementation (of Object class) would be considered along with the the Equal method's evaluation. For object to be considered equal their hash code should be the same.

However for the unit test, I would suggest don't rely heavily on Equal method's implementation. Whatever Property you want to ascertain compare those properties of the object by yourself because again the Equal method could be the custom implementation so there are possibility it might contain errors at the end of the day. So better trust upon the system defined class's Equal method for unit testing.

表情可笑 2024-08-27 05:26:35

Deepak:这意味着最终我不会比较这些对象。比较对象属性值。正确..这个相等的覆盖方法仅适用于特定的对象...这是限制而不是正确的方法...

这是一个很好的链接...在准备 UnitTest 之前为测试帮助创建自己的类

http://manfred-ramoser.blogspot.com/2007/11/c-unit-testing -helper.html

Deepak : That means at the end of the day I will not compare the objects. Compare the Objects Properties Value. Correct..This equal override method is only for particular Object...This is limitation not a correct way...

Here Is good Link...Before Prepare UnitTest make your own class for Testing Help

http://manfred-ramoser.blogspot.com/2007/11/c-unit-testing-helper.html

阿楠 2024-08-27 05:26:35

https://github.com/kbilsted/StatePrinter 专门用于将对象图转储为字符串表示形式编写简单的单元测试的目的。

  • 它带有断言方法,可以输出正确转义的字符串,轻松复制粘贴到测试中以纠正它。
  • 它允许自动重写单元测试
  • 它与所有单元测试框架集成
  • 与JSON序列化不同,支持循环引用
  • 您可以轻松过滤,因此只有部分类型被转储

给定

class A
{
  public DateTime X;
  public DateTime Y { get; set; }
  public string Name;
}

您可以以类型安全的方式,并使用自动完成Visual Studio 的包含或排除字段。

  var printer = new Stateprinter();
  printer.Configuration.Projectionharvester().Exclude<A>(x => x.X, x => x.Y);

  var sut = new A { X = DateTime.Now, Name = "Charly" };

  var expected = @"new A(){ Name = ""Charly""}";
  printer.Assert.PrintIsSame(expected, sut);

https://github.com/kbilsted/StatePrinter has been written specifically to dump object graphs to string representation with the aim of writing easy unit tests.

  • It comes witg Assert methods that output a properly escaped string easy copy-paste into the test to correct it.
  • It allows unittest to be automatically re-written
  • It integrates with all unit testing frameworks
  • Unlike JSON serialization, circular references are supported
  • You can easily filter, so only parts of types are dumped

Given

class A
{
  public DateTime X;
  public DateTime Y { get; set; }
  public string Name;
}

You can in a type safe manner, and using auto-completion of visual studio include or exclude fields.

  var printer = new Stateprinter();
  printer.Configuration.Projectionharvester().Exclude<A>(x => x.X, x => x.Y);

  var sut = new A { X = DateTime.Now, Name = "Charly" };

  var expected = @"new A(){ Name = ""Charly""}";
  printer.Assert.PrintIsSame(expected, sut);
黒涩兲箜 2024-08-27 05:26:35

这是典型的等价问题,看起来接受的答案并不是一个好的答案。我会尝试解释原因。

想象一下以下情况 - 您必须在后端编写集成测试,以确保它正确存储您的域对象。
您有一个代码:

[TestMethod]
    [Description(@"Sequentially perform operations
                 1. Save new item in DB
                 2. Get same Item from DB
                 Ensure that saved and get Items are equivalent")]
    public void Repository_Create_Test()
    {
        var initialItem = GetTestItem();
        //create item and check it is created correct
        initialItem.ID = repository.Create(initialItem, userID, ownerID);
        Item resultItem = repository.GetById(initialItem.ID, ownerID);
        resultItem.Should().NotBeNull();
        Assert.AreEqual(initialItem, resultItem);
    }

因此,您需要验证从存储中读取的对象是否与我们发送到存储的对象绝对等价。在这里,重写 Equals 是一个简单的第一猜测。对于这种情况,我们需要设置 Equals 来比较所有对象字段。但从 DDD 的角度来看,这是完全错误的。领域实体通过不可变键(或主键)来区分,而不是通过所有可变字段来区分。因此,如果我们对 HR 领域进行建模,并且假设“X 先生”有一个新的电话号码,那么他仍然是原来的“X 先生”。

话虽如此,我目前正在使用 FluentAssertions 框架,该框架具有相当强大的等效性检查功能。像这样:

resultItem.ShouldBeEquivalentTo(initialItem);

That's typical equivalence problem and looks like accepted answer is not a good one. I'll try to explain why.

Imagine the following - you have to write integration test on your backend to assure it stores your domain object correcty.
You have a code:

[TestMethod]
    [Description(@"Sequentially perform operations
                 1. Save new item in DB
                 2. Get same Item from DB
                 Ensure that saved and get Items are equivalent")]
    public void Repository_Create_Test()
    {
        var initialItem = GetTestItem();
        //create item and check it is created correct
        initialItem.ID = repository.Create(initialItem, userID, ownerID);
        Item resultItem = repository.GetById(initialItem.ID, ownerID);
        resultItem.Should().NotBeNull();
        Assert.AreEqual(initialItem, resultItem);
    }

So, you need to verify that the object read from storage is absolute equivalent of the object that we've send to the storage. Overriding Equals is an easy first guess here. For this case we need to setup Equals to compare all objects fields. But from DDD perspective thats just plain wrong. Domain Entities are distinguished by immutable key (or primary key) and not by all the mutable fields. So, if we are modelling HR domain and hypothetical 'Mister X' has a new phone number, he still remains the very same 'Mister X'.

All that said, I've currently using FluentAssertions Framework that has rather powerful facility for equivalence check. Like this:

resultItem.ShouldBeEquivalentTo(initialItem);
终止放荡 2024-08-27 05:26:35

我知道这是一个老问题,但当我阅读答案时,我想到了一个简单的技巧。也许其他人已经知道这个黑客,但由于这里没有提到它......

我已经将 Newtonsoft.Json 作为我的项目的一部分。因此,我可以轻松地在预期和实际上使用 JsonConvert.SerializeObject(obj) 。那么它只是两个字符串的 Assert.AreEqual 。

为我工作:)

I know this is an old question, but as I was reading through the answers I thought of an easy hack. Maybe others already know this hack, but since it isn't mentioned here...

I already have Newtonsoft.Json as part of my project. So I can easily use the JsonConvert.SerializeObject(obj) on both the expected and actual. Then it is just Assert.AreEqual for two strings.

Worked for me :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文