[英]How do I fake the return of a built-in method in C# unit test?
我有一個公共 static 方法,它使用隨機 class 的 object 來生成 Z157DB7DF53002357551ZD366 然后將 integer 設為 List 的索引。 我想測試方法的邏輯,同時控制隨機對象的 Next 方法返回的內容。
public class RandomGenerator
{
// a static method which produces a random selection from a List
public static string GetRandomListMember(List<string> anyStringList)
{
Random rand = new Random();
int randomInt = rand.Next(anyStringList.Count);
return anyStringList[randomInt];
}
}
從我的 MSTest 文件中:
[TestClass]
public class RandomGeneratorSpec
{
[TestMethod]
public void GetRandomListMember_ListOfStrings()
{
List<string> strings = new List<string> { "red", "yellow", "green" };
Mock<Random> mockRandom = new Mock<Random>();
mockRandom.Setup(rand => rand.Next(strings.Count)).Returns(() => 2); // 2!
string result = RandomGenerator.GetRandomListMember(strings);
Assert.AreEqual("green", result);
}
}
我希望 mockRandom.Next 每次在此測試中運行時返回 2 。 顯然,這不是這樣做的方法。 我一直在搜索示例,但它們似乎都使用 object 上的方法和實例方法而不是 static 方法。
在對使用它的方法進行單元測試時,如何控制內置方法返回的內容?
您可以使用從System.Random
class 重新定義的任何方法在本地創建自己的Random
class。
class Program
{
static void Main(string[] args)
{
var rand = new Random();
int next = rand.Next(); // uses my local Random class.
}
}
class Random
{
public int Next() => 2;
}
考慮重構以實現更可維護的設計
public class RandomGenerator {
private readonly Random random;
public RandomGenerator(Random random = default(Random)) {
this.random = random ?? new Random();
}
public string GetRandomListMember(List<string> anyStringList) {
int randomInt = random.Next(anyStringList.Count);
return anyStringList[randomInt];
}
}
這允許更靈活地使用和測試主題 class
[TestClass]
public class RandomGeneratorSpec {
[TestMethod]
public void GetRandomListMember_ListOfStrings() {
//Arrange
List<string> strings = new List<string> { "red", "yellow", "green" };
string expected = "green";
Mock<Random> mockRandom = new Mock<Random>();
mockRandom.Setup(rand => rand.Next(strings.Count)).Returns(() => 2); // 2!
var subject = new RandomGenerator(mockRandom.Object);
//Act
string actual = subject.GetRandomListMember(strings);
//Assert
Assert.AreEqual(expected, actual);
}
}
理想情況下,如果將此生成器用作服務,它應該有自己的抽象
public interface IRandomGenerator {
string GetRandomListMember(List<string> anyStringList);
}
public class RandomGenerator : IRandomGenerator {
//...omitted for brevity
}
這樣它就可以在需要的地方顯式注入,而不是靜態地用作緊密耦合的依賴項,這可以被認為是代碼異味。
我在評論中的建議示例:
[TestClass]
public class RandomGeneratorSpec
{
[TestMethod]
public void GetRandomListMember_ListOfStrings()
{
List<string> strings = new List<string> { "red", "yellow", "green" };
string result = RandomGenerator.GetRandomListMember(strings);
Assert.IsTrue(strings.Contains(result));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.