[英]Mocking Regex.IsMatch()
因此,我有自己的Luhn算法實現,並且正在使用正則表達式來驗證用戶的輸入。
我繼續進行單元測試,發現自己遇到了這個問題:
Mock<Regex> regexMock = new Mock<Regex>();
regexMock.Setup(r => r.IsMatch(It.IsAny<string>())).Returns(true);
注意: 我正在使用Moq框架進行模擬
但是不知何故,代碼的最后一行拋出了異常
在非虛擬(在VB中可重寫)成員上的無效設置:r => r.IsMatch(It.IsAny <string>())
我想知道我必須使用哪些替代方法來解決我的模擬問題,或者可以采取一些解決方法。
提前致謝!
編輯:
好的,我的測試如下所示:
Mock<Regex> regexMock = new Mock<Regex>();
regexMock.Setup(r => r.IsMatch(It.IsAny<string>())).Returns(true);
Mock<IRegexBuilder> builderMock = new Mock<IRegexBuilder>();
builderMock.Setup(m => m.Build()).Returns(regexMock.Object);
LuhnAlgorithm luhn = new LuhnAlgorithm(builderMock.Object);
string input = "7992739871";
ushort expected = 3;
object output = luhn.GenerateChecksum(input);
Assert.IsInstanceOfType(output, typeof(ushort));
Assert.AreEqual(expected, (ushort)output);
我有這個IRegexBuilder
,這是我為幫助創建Regex而制作的另一個類。 重要的是最終的Regex對象是通過調用IRegexBuilder.Build()
方法制成的。
現在,我可以模擬該方法並返回固定的Regex,例如:
builderMock.Setup(m => m.Build()).Returns(new Regex("\d+"));
但我不想在測試中定義我的驗證。
伙計們,我希望我的驗證(無論如何進行)都不會影響我的測試,我想模擬輸入匹配以返回true或false,而與進行驗證的方式無關。 如果我在測試方法中創建自己的Regex,那么以后無論何時更改驗證邏輯,都必須更改測試。
為什么要模擬正則表達式?
盡管regex是Luhn實現的內部依賴項,但它不是應該注入的依賴項,因此不應被嘲笑。
如果執行Luhn檢查取決於您的驗證代碼,以及驗證它是否執行Luhn檢查的內容,則可以有一個接口/抽象類,其中實現可以在內部進行正則表達式。
可能是
interface ICardValidator
{
bool IsCardValid(string cardNumber);
}
class LuhnCardValidator : ICardValidator
{
private static readonly Regex _cardRegex = new Regex(...);
bool IsCardValid(string cardNumber)
{
return Regex.IsMatch(cardNumber);
}
}
您可以針對LuhnCardValidator
編寫單元測試,以驗證您的Luhn檢查是否有效。
[Test]
[TestCase("4242424242424242")
public void ShouldBeValid(string cardNumber)
{
Assert.IsTrue(new LuhnCardValidator().IsCardValid(cardNumber));
}
您還可以針對依賴ICardValidator
代碼編寫測試,例如說驗證失敗時,它會向用戶顯示適當的錯誤消息。
[Test]
public void ShouldPresentCardFailedMessage()
{
var mockCardValidator = new Mock<ICardValidator>();
mockCardValidator.Setup(x => x.IsCardValid(It.IsAny<string>()).Returns(false);
var validationSummary = new ValidationSummary(mockCardValidator.Object);
validationSummary.ValidateThePage(...);
var errors = validationSummary.GetErrors();
Assert.IsTrue(errors.Any(x => x.Message == "Credit card number is not valid"));
}
如果正則表達式表示復雜的算法,則可以將匹配封裝在具有接口的自定義類中,並依賴注入(或模擬)。
如果它是基本的驗證,那么我根本不會嘲笑它。 您會嘲笑String.Contains()
嗎?
當您使用Moq創建模擬時,它將創建實現您正在模擬的接口的類,或者從您正在模擬的類繼承的類。 生成的類應提供您要嘲笑的成員的自己的實現。 使用接口很簡單,因為沒有實現。 具有類的成員應該是抽象的或虛擬的。 Regex.IsMatch
不是抽象的,也不是虛擬的。 因此,Moq不能為創建該成員而創建其自己的實現。
您應該使用Moq可以處理的東西。 通常,某些包裝器類具有虛擬方法或實現某些接口。 該類應將工作委托給Regex
類:
public interface IWrapper // use appropriate name of interface
{
bool IsValid(string value)
}
這個接口很容易被嘲笑。 現在,您可以為使用此接口的客戶端編寫測試。 對於現實生活,您將需要將正則Regex
工作委托給Regex
:
public class Wrapper : IWrapper
{
public bool IsValid(string value)
{
// use Regex here
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.