C# 如何检查具有特定值的项目是否是SelectList的一部分?
在为一个带有C# 如何检查具有特定值的项目是否是SelectList的一部分?,c#,asp.net-mvc,C#,Asp.net Mvc,在为一个带有SelectList属性的模型编写单元测试时,我有点不知所措。我将我的情况归结为以下单元测试: [Test] public void SanityCheck() { var rawOptions = new[] { (int?)null, 0, 1 }; var selectList = new SelectList(rawOptions.Select(a => new { Value = a, Text = a.ToString() })); Asse
SelectList
属性的模型编写单元测试时,我有点不知所措。我将我的情况归结为以下单元测试:
[Test]
public void SanityCheck()
{
var rawOptions = new[] { (int?)null, 0, 1 };
var selectList = new SelectList(rawOptions.Select(a => new { Value = a, Text = a.ToString() }));
Assert.That(selectList.Count(item => item.Value == null), Is.EqualTo(1));
}
该测试失败(“预期1,实际3”)。但为什么
经过一段时间的尝试,我意识到selectList
实际上是一个selectList
,因此我尝试将测试更改为更具体的测试:
[Test]
public void SanityCheck()
{
var rawOptions = new[] { (int?)null, 0, 1 };
var selectList = new SelectList(rawOptions.Select(a => new { Value = a, Text = a.ToString() }));
Assert.That(selectList.Items.Count(item => item.Value == null), Is.EqualTo(1));
}
编译失败,并显示以下消息:
“System.Collections.IEnumerable”不包含“Count”的定义,并且找不到接受“System.Collections.IEnumerable”类型的第一个参数的扩展方法“Count”(是否缺少using指令或程序集引用?)
我可以理解,因为Items
属性是非泛型IEnumerable
类型。但现在我不知道该如何编写我的Assert
。选择列表
上没有值
属性或任何类似属性
我错过了什么?如果我将动态对象用于我的选择列表
,这是不可能的吗?有什么建议吗
起初我以为我省略了使用System.Linq的
代码>在我的文件中,但它在那里。为了确保没有副作用导致我的问题,我在一个可再现的场景中执行了以下操作以获得上述结果:
在VS 2012中,创建一个新的.NET 4.5类库项目
使用NuGet添加NUnit 2.6.4
使用NuGet添加Microsoft ASP.NET MVC 5.2.3(以及提到的依赖项)
将下面的代码复制粘贴到自动创建的Class1.cs
文件中:
复制:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using NUnit.Framework;
namespace ClassLibrary2
{
[TestFixture]
public class Class1
{
[Test]
public void SanityCheck1()
{
var rawOptions = new[] { (int?)null, 0, 1 };
var selectList = new SelectList(rawOptions.Select(a => new { Value = a, Text = a.ToString() }));
Assert.That(selectList.Count(item => item.Value == null), Is.EqualTo(1));
}
[Test]
public void SanityCheck2()
{
var rawOptions = new[] { (int?)null, 0, 1 };
var selectList = new SelectList(rawOptions.Select(a => new { Value = a, Text = a.ToString() }));
// Will not compile:
//Assert.That(selectList.Items.Count(item => item.Value == null), Is.EqualTo(1));
}
}
}
SelectList。项的类型为IEnumerable
。为了能够对它执行linq查询,您需要将它转换为某种类型的强类型泛型IEnumerable
但是,如果您像在示例中那样使用匿名类型,我认为这是不可能的。除非您愿意动态生成表达式,否则编译器需要知道您使用的类型。因为没有为非泛型的IEnumerable
定义Count()
,这就是为什么会出现编译器错误
相反地,SelectList
本身继承了IEnumerable
,这是IEnumerable
的一种通用类型,可以为其编写linq查询。我认为,当您以IEnumerable
的形式访问SelectList
实例时,在幕后SelectList
会将您提供给SelectListItems.Items
的匿名类型转换为SelectListItems
实例
您真的需要使用匿名类型来生成选择列表项吗?请尝试以下代码:
[Test]
public void SanityCheck()
{
var rawOptions = new[] { (int?)null, 0, 1 };
var selectList = new SelectList(rawOptions.Select(a => new SelectListItem { Value = a.ToString(), Text = a.ToString() }));
Assert.That(selectList.Items.Cast<SelectListItem>().Count(item => String.IsNullOrEmpty(item.Value)), Is.EqualTo(1));
}
[测试]
public void SanityCheck()
{
var rawOptions=new[]{(int?)null,0,1};
var-selectList=new-selectList(rawOptions.Select(a=>new-SelectListItem{Value=a.ToString(),Text=a.ToString()}));
Assert.That(selectList.Items.Cast().Count(item=>String.IsNullOrEmpty(item.Value)),是.EqualTo(1));
}
请注意,selectList.Items.Cast()
如果为selectList
匿名类型提供数据,则运行时会失败。这表示SelectList.items
中的项目在添加时会被保留。实际结果为3,因为您尚未设置SelectList项目的值
属性(它们都为空)。您正在使用接受IEnumerable
的SelectList
构造函数的。这通常在集合为值类型时使用。例如:
List<string> items = new List<string>() {"Option 1", "Option 2" };
SelectList selectList = new SelectList(items);
请注意,选项标记没有值
属性(这不是必需的,因为选择选项会将select的值设置为选项文本)
如果您在本例中使用DropDownListFor()
,您将看到生成的输出有多奇怪(您有一组匿名对象,并且SelectList
构造函数在内部调用每个项的ToString()
方法)
{Value=,Text=}
{Value=0,Text=0}
{Value=1,Text=1}
您需要使用指定dataValueField
和dataTextField
var selectList = new SelectList(rawOptions.Select(a => new { Value = a, Text = a }), "Value", "Text");
也可能是
var selectList = new SelectList(rawOptions.Select(a => new { ID = a, Name = a }), "ID", "Name");
将生成以下html
0
1.
但是,内部null
值被转换为空字符串(生成html所必需),因此在这种情况下Assert
也将失败,因为实际结果为零。相反,您需要检查是否有空字符串
Assert.That(selectList.Count(item => item.Value == string.Empty), Is.EqualTo(1));
在任何情况下,SelectList
都不应包含“空”选项。相反,您应该使用接受标签选项的DropDownListFor()
来生成null
值。我知道您提到的最后一个选项,但我还不确定是否喜欢该选项,因为这会阻止我对视图是否正确显示显式选项进行单元测试“空”。无论如何:谢谢你的明确解释!