[英]Whats the Difference between Object.Equals(obj, null) and obj == null
[英]How to mock `object.Equals(object obj)` for an interface using Moq
我有一個有趣的問題包圍你的頭。 考慮一下這樣的界面:
public interface IMyThing
{
int Id { get; }
}
現在我想測試使用此接口的代碼。 也許有一些LINQ魔術。 像這樣的東西:
public class SomeClass
{
private IMyThing _thing;
...
public bool HasThing(IEnumerable<IMyThing> things)
{
return things.Contains(_thing);
}
}
我正在使用Moq
IMyThing
實現IMyThing
所有對象:
public static IMyThing MockMyThing(int newId)
{
var mock = new Mock<IMyThing>();
mock.Setup(s => s.Id).Returns(newId);
mock.Setup(s => s.Equals(It.IsAny<object>())).Returns<object>(obj =>
{
if (typeof(IMyThing).IsAssignableFrom(obj.GetType()))
{
return ((IMyThing)obj).Id == newId;
}
return false;
});
return mock.Object;
}
這就是事情。 上面的代碼編譯沒有警告,但永遠不會工作。 Moq
為Equals()
方法創建了一個攔截器,但它永遠不會到達。 而是調用對象代理的equals方法。 我譴責的事實是我在嘲笑一個界面而不是一個具體的類。
更新:剛剛意識到Moq
甚至沒有創建攔截器。
當然,我可以像這樣擴充IMyThing
界面:
public interface IMyThing : IEquatable<IMyThing>
{
int Id { get; }
}
LINQ運算符將識別IEquatable<T>
接口並使用它。
我不想這樣做是因為:
IMyThing
對象 IEquatable<T>
不是為了這個目的 你怎么解決這個問題?
我最終為Github上的Moq
項目貢獻代碼(參見問題#248 )。 通過這種更改,可以模擬object.GetHashCode()
object.Equals(object obj)
, object.GetHashCode()
和object.GetHashCode()
object.ToString()
,甚至可以模擬接口模擬。
讓我們看看它是否被接受。
我認為問題來自於Equals
方法不在你嘲笑的界面上。 如果您使用可覆蓋的Equals
方法創建一個類(即使它什么也不做),那么您可以模擬它。
public class MyTestThing : IMyThing
{
public virtual int Id { get; }
public override bool Equals(object obj)
{
return base.Equals(obj);
}
}
[TestCase(55)]
public void Can_mock_equals_method(int newId)
{
var mockThing = new Mock<MyTestThing>();
mockThing.Setup(t => t.Id).Returns(newId);
mockThing.Setup(t => t.Equals(It.IsAny<object>()))
.Returns<object>(t => (t as IMyThing)?.Id == newId);
Assert.That(mockThing.Object.Equals(new MyRealThing(newId)));
}
請注意,如果您在MyTestThing
上MyTestThing
Equals
方法, MyTestThing
此測試將失敗,因為Moq無法再模擬它。
如果您要創建這樣的測試類,那么在類本身中實際完全實現Equals
可能更有用,因此您不必費心使用Moq進行設置。 您甚至可以更進一步創建一個抽象基類,其中唯一實現的方法是Equals
並在使用Moq的測試中使用它,並從中派生您的實際實現。
如果執行比較的方式可能會發生變化,則不應使用直接比較,而是使用可以為您進行比較的對象。
考慮對您的類進行更改,如下所示:
public class SomeClass
{
private IMyThing _thing;
public bool HasThing(IEnumerable<IMyThing> things, IEqualityComparer<IMyThing> comparer = null)
{
comparer = comparer ?? EqualityComparer<IMyThing>.Default;
return things.Contains(_thing, comparer);
}
}
然后你只需要模擬比較器。
也許我完全不理解你,但我沒有看到一個擴展或者覆蓋Equy Equals()
函數的IMyThing
? 所以我想我的第一種方法將是overide或extandes功能,如果它不起作用我將IMyThing : IEquatable<IMyThing>
,我知道IEquatable<T>
不是為了這個目的,但它關閉。 而最后我不認為你需要這樣做,但它存在,只需創建一個像bool IsEquals(IMyThing other){//check if equals}
的函數
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.