[英]Best way to override a class's dependency for a unit test?
tl;博士試圖了解測試 class 的正確方法,但需要覆蓋依賴項的某些成員。 下面我描述了我嘗試子類化此依賴項的思考過程,但也許我應該重新實現依賴項的接口並跳過嘗試完全覆蓋和子類化依賴項?
好的,我正在嘗試對依賴於調用的 object 的 class 進行單元測試。 我想讓該對象的屬性可變,這樣我就可以在測試期間更改它們,而不是讓它調用網絡。 我認為這很棘手,因為父 class 在相關屬性上只有一個吸氣劑。 我對 C# 有點陌生,並且想確認/糾正我迄今為止的推理。
我有一個界面:
public interface ISettings
{
bool IsFooEnabled { get; }
}
還有一個 class
public class Settings : ISettings
{
public bool IsFooEnabled => bool.Parse(DoNetworkStuff());
}
我在我的測試中制作了這個 class:圖 1:
public class TestSettings : Settings
{
public bool IsFooEnabled = true;
}
而且我希望將覆蓋的 object 傳遞到對象的構造函數中,因為通常SomeObject
需要ISettings
object:
public void Test()
{
TestSettings s = new TestSettings();
s.IsFooEnabled = true;
SomeObject s = new SomeObject(s);
}
因此測試失敗,因為DoNetworkStuff()
返回null
:圖 1.1:
System.ArgumentNullException : Value cannot be null. (Parameter 'value')
Stack Trace:
Boolean.Parse(String value)
Settings.get_IsFooEnabled() line 113
我想是因為
相同的錯誤:圖 2:
public class TestSettings : Settings
{
public bool IsFooEnabled { get; set; }
}
和圖3:
public class TestSettings : Settings
{
public bool IsFooEnabled => false;
}
和圖4:
public class TestSettings : Settings
{
public bool IsFooEnabled = false;
}
都返回圖 1.1 的錯誤。 這意味着Settings.IsFooEnabled
沒有被覆蓋,它仍在嘗試調用並獲取 null。 我對此感到困惑,因為我認為在子類中,子類的定義優先。 但是預期的類型是Settings
,所以我認為TestSettings
IsFooEnabled
被忽略了。
但這有效:圖 4:
public class TestSettings : Settings
{
public override bool IsFooEnabled => false;
}
但是我必須將設置更改為虛擬,否則它會抱怨,這是有道理的,因為在父 class 中沒有虛擬就無法覆蓋:圖 5:
public class Settings : ISettings
{
public virtual bool IsFooEnabled => bool.Parse(DoNetworkStuff());
}
我還嘗試自行覆蓋該屬性:圖 6:
public class TestSettings : Settings
{
public override bool IsFooEnabled = false;
}
但是得到了這個錯誤:
Severity Code Description Project File Line Suppression State
Error CS0106 The modifier 'override' is not valid for this item Foo.Unit.Tests Foo.cs 33 N/A
這是有道理的,因為您不能覆蓋屬性。 我認為總的來說我有點困惑為什么屬性聲明不會覆蓋父類的屬性表達式。 我認為父母有一個事實; 意味着它必須是另一個覆蓋它的吸氣劑,它不能只是一個屬性?
終極問題,這是go關於情況的正確方法嗎? 我是否從根本上誤解了 C# 的 inheritance 的某些部分? 很抱歉啰嗦了,但真的很想了解這里發生了什么。
顯然,您不希望TestSettings
直接實現ISettings
,因為您還需要實現大量其他成員。
解決這個問題的一種方法是“部分模擬”。 許多 mocking 庫都提供了這一點。 使用 mocking 庫通常比“手動” mocking 更好。
除此之外:您可以覆蓋屬性。 不工作的情況不是一個屬性,而只是一個字段。 以下變體應該可以正常工作(它們只是定義屬性的不同方式):
public class TestSettings : Settings
{
public override bool IsFooEnabled
{
get;
}
}
public class TestSettings : Settings
{
public override bool IsFooEnabled => true;
}
這不起作用,因為它是一個字段,而不是 C# 中不同的屬性。
public class TestSettings : Settings
{
public override bool IsFooEnabled = true; // syntax error
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.