簡體   English   中英

模擬Regex.IsMatch()

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM