删除 Equals 方法时出现 RhinoMocks 异常

发布于 2024-08-04 16:16:08 字数 2546 浏览 10 评论 0原文

我在为对象设置 Equals 方法测试时遇到问题。

有问题的对象是由此接口定义的:

public interface IHours {
    ITimeOfDay OpenAt { get; set; }
    ITimeOfDay CloseAt { get; set; }
    DateTime ValidFrom { get; set; }
    DateTime ValidTo { get; set; }
    bool isCovered(DateTime time);
}

并且它包含对 ITimeOfDay 的引用,定义如下:

public interface ITimeOfDay {
    DateTime Time { get; set; }
    int Hour { get; }
    int Minute { get; }
    int Second { get; }
}

现在我想要 Equals of the Hours : IHours 来检查 OpenAt 和 CloseAt IHours。为了进行设置,我尝试将这些属性值存根,然后根据我的特定测试需要它们返回 true 和 false。

    [SetUp]
    public virtual void SetUp() {
        mocks = new MockRepository();

        defaultHours = getHours();
        otherHours = getHours();

    }

    [TearDown]
    public virtual void TearDown() {
        mocks.ReplayAll();
        mocks.VerifyAll();
    }

    [Test(Description = "Equals on two Hours should regard the fields")]
    public void Equals_TwoValueEqualledObjects_Equal() {
        var openAt = mocks.Stub<ITimeOfDay>();
        var closeAt = mocks.Stub<ITimeOfDay>();

        closeAt                                   //this is line 66, referenced in the error stacktrace
            .Stub(o => o.Equals(null))
            .IgnoreArguments()
            .Return(true);

        openAt
            .Stub(c => c.Equals(null))
            .IgnoreArguments()
            .Return(true);
        mocks.ReplayAll();

        defaultHours.OpenAt = openAt;
        otherHours.OpenAt = openAt;

        defaultHours.CloseAt = closeAt;
        defaultHours.CloseAt = closeAt;

        Assert.That(defaultHours, Is.EqualTo(otherHours));
        Assert.That(defaultHours.GetHashCode(), Is.EqualTo(otherHours.GetHashCode()));
    }

但当我运行它时,我得到了这个神秘的错误:

System.InvalidOperationException: Type 'System.Boolean' doesn't match the return type   'System.Collections.Generic.IList`1[NOIS.Model.Interfaces.IAircraft]' for method 'IAircraftType.get_Aircrafts();'
at Rhino.Mocks.Expectations.AbstractExpectation.AssertTypesMatches(Object value)
at Rhino.Mocks.Expectations.AbstractExpectation.set_ReturnValue(Object value)
at Rhino.Mocks.Impl.MethodOptions`1.Return(T objToReturn)
at Nois.Test.Model.Entities.HoursTest.Equals_TwoValueEqualledObjects_Equal() in HoursTest.cs: line 66 

IAircraftType 接口是同一命名空间的一部分,但在测试、接口或实现类中没有引用它。我不明白为什么它会干扰。据我所知,没有任何参考资料。

我正在使用 - Rhino.Mocks v3.5.0.1337 - NUnit.Framework v2.5.0.8332

有人知道吗?

I've a problem setting up a test for an Equals method on an object.

The object in question is defined by this interface:

public interface IHours {
    ITimeOfDay OpenAt { get; set; }
    ITimeOfDay CloseAt { get; set; }
    DateTime ValidFrom { get; set; }
    DateTime ValidTo { get; set; }
    bool isCovered(DateTime time);
}

and it contains references to ITimeOfDay defined such:

public interface ITimeOfDay {
    DateTime Time { get; set; }
    int Hour { get; }
    int Minute { get; }
    int Second { get; }
}

Now I want the Equals of the Hours : IHours to check the OpenAt and CloseAt IHours. To set this up I try to stub those property-values out, and just return true and false depending on what my particular test needs them to be.

    [SetUp]
    public virtual void SetUp() {
        mocks = new MockRepository();

        defaultHours = getHours();
        otherHours = getHours();

    }

    [TearDown]
    public virtual void TearDown() {
        mocks.ReplayAll();
        mocks.VerifyAll();
    }

    [Test(Description = "Equals on two Hours should regard the fields")]
    public void Equals_TwoValueEqualledObjects_Equal() {
        var openAt = mocks.Stub<ITimeOfDay>();
        var closeAt = mocks.Stub<ITimeOfDay>();

        closeAt                                   //this is line 66, referenced in the error stacktrace
            .Stub(o => o.Equals(null))
            .IgnoreArguments()
            .Return(true);

        openAt
            .Stub(c => c.Equals(null))
            .IgnoreArguments()
            .Return(true);
        mocks.ReplayAll();

        defaultHours.OpenAt = openAt;
        otherHours.OpenAt = openAt;

        defaultHours.CloseAt = closeAt;
        defaultHours.CloseAt = closeAt;

        Assert.That(defaultHours, Is.EqualTo(otherHours));
        Assert.That(defaultHours.GetHashCode(), Is.EqualTo(otherHours.GetHashCode()));
    }

But I get this cryptic error when I run it:

System.InvalidOperationException: Type 'System.Boolean' doesn't match the return type   'System.Collections.Generic.IList`1[NOIS.Model.Interfaces.IAircraft]' for method 'IAircraftType.get_Aircrafts();'
at Rhino.Mocks.Expectations.AbstractExpectation.AssertTypesMatches(Object value)
at Rhino.Mocks.Expectations.AbstractExpectation.set_ReturnValue(Object value)
at Rhino.Mocks.Impl.MethodOptions`1.Return(T objToReturn)
at Nois.Test.Model.Entities.HoursTest.Equals_TwoValueEqualledObjects_Equal() in HoursTest.cs: line 66 

The IAircraftType interface is a part of the same namespace, but nowhere in the test, interface or implementing class is it referenced. I do not understand why it interferes. There is no reference to it as far as I can gather.

I am using
- Rhino.Mocks v3.5.0.1337
- NUnit.Framework v2.5.0.8332

Anyone have any idea?

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

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

发布评论

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

评论(2

塔塔猫 2024-08-11 16:16:08

是的,这很复杂 - 错误很疯狂,这与 IAircraft 无关。本质上,问题在于接口不是类,因此不会从对象继承。换句话说 - closeAt 没有 Equals 方法来存根。

事实上,您甚至可以在转换为接口的对象上显式调用 Equals(),这可能有点语言错误。

有两种方法可以解决此问题,然后

  1. 不要模拟接口,而是模拟实现mocks.Stub() - 这确实有一个虚拟的 equals 方法,因此您的代码可以工作。
  2. 更好的是,将 Equals 方法添加到您的界面中。一旦你这样做了,你将能够覆盖它,并且由于所有类都继承自对象,因此你不必显式地实现它(除非你愿意)。

换句话说,

var intrface = MockRepository.GenerateStub<IInterface>();
intrface.Stub(x => x.Equals(null)).IgnoreArguments().Return(true); 

什么时候中断

public interface IInterface {
}

,什么时候工作

public interface IInterface {
  bool Equals(object obj);
}

Yeah this is complicated - the error is crazy, this has nothing to do with IAircraft. Essentially the issue is that an interface is not a class and hence does not inherit from object. In other words - closeAt does not have an Equals method to stub out.

As a matter of fact, its probably a bit of a language flub that you can even call Equals() explicitly on an object cast to an interface.

Two ways to fix this then

  1. Don't mock the interface, mock the implementation mocks.Stub() - this does have an equals method that is virtual so your code will work.
  2. Even better, add an Equals method to your interface. Once you do that you will be able to override it and since all classes inherit from object you won't have to implement it explcitly ever (unless you want to).

In other words

var intrface = MockRepository.GenerateStub<IInterface>();
intrface.Stub(x => x.Equals(null)).IgnoreArguments().Return(true); 

Breaks when

public interface IInterface {
}

but works when

public interface IInterface {
  bool Equals(object obj);
}
奶茶白久 2024-08-11 16:16:08

除非我遗漏了什么,否则一天中的时间应该是一个简单的不可变对象。所以我只是将它实现为一个小的、经过测试的值类。然后你就可以使用真正的Equals方法了。

Unless I'm missing something, Time of Day should be a simple immutable object. So I'd just implement it as a small, tested value class. Then you can use the real Equals method.

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