c# - 单元测试win表单验证方法
问题描述
我试图为 CoordinateValidation 创建一些单元测试,但它需要将一些控件传递给它。我试过做MVC(还是新手),但我认为我做得不好,好像我不必传递控件一样?
是我没有正确完成 MVC 还是我错过了什么?
这是我尝试测试的方法和实际的单元测试:
private static bool ValidRange(TextBox tb)
{
float x = float.Parse(tb.Text.Split(',')[0]);
float y = float.Parse(tb.Text.Split(',')[1]);
if ((x < 10 || x > 1000) || (y < 10 || y > 730))
{
return false;
}
return true;
}
public static bool CoordinateValidation(Panel pointsPanel, ErrorProvider errorProvider)
{
bool status = true;
Regex regex = new Regex(@"^((\d+\.?\d*),{1}(\d+\.?\d*))$");
foreach (TextBox tb in pointsPanel.Controls)
{
Match match = regex.Match(tb.Text);
if (!match.Success)
{
errorProvider.SetError(tb, "Invalid coordinates!");
status = false;
}
else if (!ValidRange(tb))
{
errorProvider.SetError(tb, "Invalid range!");
status = false;
}
else
{
errorProvider.SetError(tb, "");
}
}
return status;
}
namespace BezierLibrary.UnitTests
{
[TestClass]
public class BezierHelperTests
{
[TestMethod]
public void CoordinateValidation_InvalidCoordinate_ReturnFalse()
{
//Arrange
var panel = new Panel();
var textbox = new TextBox();
var errorProvider = new ErrorProvider();
panel.Controls.Add(textbox);
textbox.Text = "5";
//Act
var result = BezierHelper.CoordinateValidation(panel, errorProvider);
//Assert
Assert.IsFalse(result);
}
}
}
解决方案
正如 Leszek Repie 在他的评论中所说,你不应该通过控制。切勿将表示层(显示/控件)与业务层(计算)混合。因此,当用户单击确定按钮时,在 OkButtonClick 处理程序中,您从文本框中提取文本。然后将此文本作为参数传递给您的业务功能。这还具有使您的单元测试更简单的好处——您只需对测试字符串进行硬编码。
考虑使用这种形式的函数:
bool CoordinateValidation(String coordinates, ref String errorMessage )
bool ValidRange( String coordinates )
当你开始工作时,将注意力转向 CoordinateValidation()。它自己进行一些验证(验证坐标),然后调用 ValidateRange()。我建议提取坐标的验证并将该代码放在一个新函数中。然后,您的 CoordinateValidation 函数仅调用您的新函数和 ValidateRange()。
希望有帮助。
编辑 - 这是一个小例子:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click( object sender, EventArgs e )
{
List<DataTransferObject> dtos = new List<DataTransferObject>();
dtos.Add( new DataTransferObject() { Field = FieldId.FieldA, Text = textBox1.Text } );
dtos.Add( new DataTransferObject() { Field = FieldId.FieldB, Text = textBox2.Text } );
BusinessThing businessThing = new BusinessThing();
businessThing.Validate( dtos );
foreach( var dto in dtos )
{
if( dto.Error != null )
{
if( dto.Field == FieldId.FieldA )
{
label1.Text = dto.Error;
}
// etc
}
}
}
}
public enum FieldId
{
FieldA,
FieldB
}
public class DataTransferObject
{
public FieldId Field { get; set; }
public String Text { get; set; }
public String Error { get; set; } = null;
}
public class BusinessThing
{
private Regex regex = new Regex(@"^((\d+\.?\d*),{1}(\d+\.?\d*))$");
public void Validate( List<DataTransferObject> dtos )
{
foreach( var dto in dtos )
{
Validate( dto );
}
}
public void Validate( DataTransferObject dto )
{
if( ValidateCoordonate( dto ) )
{
ValidateRange( dto );
}
}
public Boolean ValidateCoordonate( DataTransferObject dto )
{
Match match = regex.Match(dto.Text);
if( match.Success )
{
return true;
}
else
{
dto.Error = "Invalid coordinates!";
return false;
}
}
public Boolean ValidateRange( DataTransferObject dto )
{
float x = float.Parse(dto.Text.Split(',')[0]);
float y = float.Parse(dto.Text.Split(',')[1]);
if( (x < 10 || x > 1000) || (y < 10 || y > 730) )
{
dto.Error = "Invalid range!";
return false;
}
return true;
}
}
}
推荐阅读
- hibernate - Hibernate Envers:阻止 onPostDelete 上的版本
- javascript - 是否可以使用 XPath 获得此结果集?
- css - CSS 网格可折叠行
- android - 如何将所有json属性解析为数组列表android
- swift - SwiftUI 网格索引超出范围
- azure - 使用 Azure 认知搜索为静态 HTML blob 存储内容编制索引未按预期工作
- sql - 在使用案例时将时间从表附加到 getdate()
- python - Pandas 多索引中的意外键错误
- python - Python requests.get 因 403 被禁止而失败,即使在使用标头和 Session 对象之后也是如此
- r - 如何使用 Roxygen2 使用单个帮助页面正确记录相同泛型的两个 S4 方法?