Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF输入验证(动态)和单元测试。最佳设计实践_C#_Wpf_Validation_Testing - Fatal编程技术网

C# WPF输入验证(动态)和单元测试。最佳设计实践

C# WPF输入验证(动态)和单元测试。最佳设计实践,c#,wpf,validation,testing,C#,Wpf,Validation,Testing,我想向现有解决方案添加一个新表单。这个解决方案已经有了一个验证器类,所以我想扩展这个类 我要创建的表单包含一个文本框(用于输入)和一个按钮。当输入格式正确时,将启用“提交”按钮。输入必须遵循某个正则表达式:“^[a-Za-z]{2}[0-9]{5}$”。我正在检查表单类中的输入(动态),如下所示: private void inputTbx_TextChanged(object sender, TextChangedEventArgs e) { SubmitButton.IsEnable

我想向现有解决方案添加一个新表单。这个解决方案已经有了一个验证器类,所以我想扩展这个类

我要创建的表单包含一个文本框(用于输入)和一个按钮。当输入格式正确时,将启用“提交”按钮。输入必须遵循某个正则表达式:“^[a-Za-z]{2}[0-9]{5}$”。我正在检查表单类中的输入(动态),如下所示:

private void inputTbx_TextChanged(object sender, TextChangedEventArgs e)
{
    SubmitButton.IsEnabled = Validator.IsInputValid(inputTbx.Text, RegexExpression);
}
我将正则表达式作为变量放在Form类中。我把它放在这里是因为它只与此表单的文本框相关

private const string RegexExpression = "^[A-Za-z]{2}[0-9]{5}$"; 
以下是验证代码:

public static bool IsInputValid(string inputToBeChecked, string regexExpression)
{
    if (inputToBeChecked == null || regexExpression == null)
    {
        return false;
    }
    var regex = new Regex(regexExpression, RegexOptions.None);
    return regex.IsMatch(inputToBeChecked);
}
到目前为止还不错。它似乎工作得很好。但我想这样对它进行单元测试:

[TestCase("aZ13579")]
public void ValidateInputOkTest(string input)
{
    Assert.IsTrue(Validator.IsInputValid(input, RegexExpression));
}
但要这样做,我必须在ValidatorTest类中有一个字符串,类似于Form类中使用的正则表达式。这似乎不是正确的方法。我真正想做的是从form类中获取正则表达式,因此我确信我使用的正则表达式是正确的。否则,正则表达式很容易失去同步

以下是问题: 这里的最佳实践是什么? 我怎样才能得到这个表达式?我尝试过使用反射来实现它,但是我得到了一个Threadstat错误,因为它是一个GUI组件。我应该移动正则表达式吗?如果是,去哪里?
我想一定有一个聪明的方法可以做到这一点。也许是个聪明的设计。欢迎您提出建议和意见。

您可能希望备份一个步骤,并开始研究“MVVM”设计模式。当您听到人们谈论不在代码中添加代码时,像这样的测试是最大的好处之一(在许多其他好处中)

MVVM是一个太大的主题,用这样一个简单的答案无法处理。我会在网上搜索,我相信其他人也有一些很好的教程

需要明确的是,这可能是一个巨大的学习曲线,但它是完全值得的。MVVM使WPF比WinForms好得多,而不仅仅是不同

为了更具体地回答您的问题,您不会测试窗口或用户控件之类的GUI对象。您将测试一个视图模型,它只是一个普通类

下面是您可能看到的内容的简化版本

public class MyScreenViewModel : INotifyPropertyChanged
{
  private const string RegexExpression = "^[A-Za-z]{2}[0-9]{5}$"; 

  public bool UserInputIsValid { get { stuff; } set { stuff; }}
  public string UserInput { get { stuff; } set { stuff; ValidateUserInput();} }

  private void ValidateUserInput()
  {
    if (UserInput == null)
    {
        return false;
    }
    var regex = new Regex(RegexExpression, RegexOptions.None);
    UserInputIsValid = regex.IsMatch(UserInput);
  }
}
MVVM中的视图模型是屏幕的真实逻辑。它将公开视图可以绑定到的用于显示/输入的简单属性,但该视图不是测试逻辑所必需的

然后,您的测试看起来像:

[TestCase("aZ13579")]
public void ValidateInputOkTest()
{
  var vm = new MyScreenViewModel();
  vm.UserInput = "SomeValidText";

  Assert.IsTrue(vm.UserInputIsValid);
}

[TestCase("aZ13580")]
public void ValidateInputNotOkTest()
{
  var vm = new MyScreenViewModel();
  vm.UserInput = "SomeInvalidText";

  Assert.IsFalse(vm.UserInputIsValid);
}

谢谢你的意见。我意识到使用代码隐藏文件是一种不好的做法。因此,回到绘图板上:-/我不会说“坏习惯”。如果您不打算在MVVM模式中编写代码,那么您所做的就完全可以了。我只是建议,从长远来看,你最好经历学习这种模式的过程。大多数人最终认为这是一种更高效的模式。谢谢你的回复。最后,我在Validator类中将Regex表达式设置为公共属性,并将验证代码保留在codebehind中。这样,可以从生产代码和测试代码中访问正则表达式。关于MVVM模式,我将尝试进一步研究它。您是否碰巧有一个指向良好起点的指针?:-)乔希·史密斯的书极受好评: