为了帮助我的团队编写可测试的代码,我提出了这个简单的最佳实践列表,以使我们的C#代码库更易于测试.(有些观点指的是Rhino Mocks的限制,这是C#的模拟框架,但规则也可能更普遍适用.)有没有人有他们遵循的最佳实践?
要最大限度地提高代码的可测试性,请遵循以下规则:
首先编写测试,然后编写代码.原因:这可确保您编写可测试代码,并确保每行代码都为其编写测试.
使用依赖注入设计类.原因:你无法模拟或测试无法看到的东西.
使用Model-View-Controller或Model-View-Presenter将UI代码与其行为分开.原因:允许在无法测试的部分(UI)最小化的同时测试业务逻辑.
不要编写静态方法或类. 原因:静态方法难以或无法隔离,Rhino Mocks无法模拟它们.
编程关闭接口,而不是类.原因:使用接口阐明了对象之间的关系.接口应该定义对象从其环境中需要的服务.此外,可以使用Rhino Mocks和其他模拟框架轻松模拟接口.
隔离外部依赖项.原因:无法测试未解析的外部依赖项.
将您想要模拟的方法标记为虚拟.原因:Rhino Mocks无法模拟非虚方法.
可以说我有以下代码:
abstract class Animal
case class Dog(name:String) extends Animal
var foo:Animal = Dog("rover")
var bar:Dog = foo //ERROR!
Run Code Online (Sandbox Code Playgroud)
如何修复此代码的最后一行?基本上,我只想做一些类似C语言的事情:
var bar:Dog = (Dog) foo
Run Code Online (Sandbox Code Playgroud) 我在我的Clojure项目(GUI应用程序)中使用Leiningen,并在项目根目录下创建了一个"resources"目录来保存我的应用程序使用的图像.
当我在测试期间在本地运行我的应用程序时,我使用相对路径"resources/logo.png"获取图像,这样可以正常工作.但是当我使用Leiningen构建一个uberjar时,Leiningen将来自资源文件夹的文件放在JAR的根文件夹中,因此我对资源文件的引用不再起作用.
使用Leiningen访问这样的资源的正确方法是什么?
我在UpdatePanel中有一个GridView.在模板字段中是我用于标记项目的按钮.在功能上,这工作正常,但按钮总是触发整页回发而不是部分回发.如何让按钮触发部分回发?
<asp:ScriptManager ID="ContentScriptManager" runat="server" />
<asp:UpdatePanel ID="ContentUpdatePanel" runat="server" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:GridView ID="OrderGrid" runat="server" AllowPaging="false" AllowSorting="false"
AutoGenerateColumns="false">
<Columns>
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:LinkButton ID="MarkAsCompleteButton" runat="server" Text="MarkAsComplete"
CommandName="MarkAsComplete" CommandArgument='<%# Eval("Id") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Name" HeaderText="Name" />
<asp:BoundField DataField="LoadDate" HeaderText="Load Date" />
<asp:BoundField DataField="EmployeeCutOffDate" HeaderText="Cut Off Date" />
<asp:BoundField DataField="IsComplete" HeaderText="Is Completed" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
Run Code Online (Sandbox Code Playgroud) 当文件更改后播放重新启动时,我偶尔会收到此错误:
play.PlayExceptions$UnexpectedException: Unexpected exception[BootException: Cannot redefine component. ID: compiler-interface-bin_2.11.6__52.0, files: /Users/kevin/.ivy2/cache/org.scala-sbt/compiler-interface-bin_2.11.6__52.0/jars/compiler-interface-bin_2.11.6__52.0-0.13.5_20140527T130009.jar]
at play.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:51) ~[na:na]
at play.PlayReload$$anonfun$taskFailureHandler$1.apply(PlayReload.scala:44) ~[na:na]
at scala.Option.map(Option.scala:145) ~[scala-library-2.11.6.jar:na]
at play.PlayReload$.taskFailureHandler(PlayReload.scala:44) ~[na:na]
at play.PlayReload$.compileFailure(PlayReload.scala:40) ~[na:na]
Run Code Online (Sandbox Code Playgroud)
这只会偶尔发生,并且总是通过重新启动IntelliJ来解决.为什么会发生这种情况,我该如何解决?
我正在通过IntelliJ运行Play,我正在使用IntelliJ 14.1.2,Scala 2.11.6和Play 2.3.8.
如何从查询而不是整个对象中获取单个列?
我可以做这样的事情来获得整个对象,但我想要的只是名字:
IList<Tribble> tribbles = session.CreateCriteria(typeof(Tribble)).List<Tribble>();
IList<string> names = new List<string>();
foreach (Tribble t in tribbles) {
names.Add(t.Name);
}
Run Code Online (Sandbox Code Playgroud)
我希望能够指定其他条件,那么是否可以排除某些列被检索?
我想将一个int列表(List)作为声明属性传递给Web用户控件,如下所示:
<UC:MyControl runat="server" ModuleIds="1,2,3" />
Run Code Online (Sandbox Code Playgroud)
我创建了一个TypeConverter来执行此操作:
public class IntListConverter : System.ComponentModel.TypeConverter
{
public override bool CanConvertFrom(
System.ComponentModel.ITypeDescriptorContext context,
Type sourceType)
{
if (sourceType == typeof(string)) return true;
return base.CanConvertFrom(context, sourceType);
}
public override object ConvertFrom(
System.ComponentModel.ITypeDescriptorContext context,
System.Globalization.CultureInfo culture, object value)
{
if (value is string)
{
string[] v = ((string)value).Split(
new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
List<int> list = new List<int>();
foreach (string s in vals)
{
list.Add(Convert.ToInt32(s));
}
return list
}
return base.ConvertFrom(context, culture, value);
}
public override …Run Code Online (Sandbox Code Playgroud) 在Scala中,是否可以在运行时获取类型的字符串表示形式?我试图沿着这些方向做点什么:
def printTheNameOfThisType[T]() = {
println(T.toString)
}
Run Code Online (Sandbox Code Playgroud) 我目前在SQL Server数据库中以小写形式存储规范化版本的字符串.例如,在我的Users表中,我有一个UserName和一个LoweredUserName字段.根据上下文,我使用T-SQL的LOWER()函数或C#的String.ToLower()方法生成用户名的小写版本以填充LoweredUserName字段.根据Microsoft的指南和Visual Studio的代码分析规则CA1308,我应该使用C#的String.ToUpperInvariant()而不是ToLower().根据微软的说法,这既是性能问题也是全球化问题:转换为大写是安全的,而转换为小写可能会导致信息丢失(例如,土耳其语'I'问题).
如果我转而使用ToUpperInvariant进行字符串规范化,我也必须更改我的数据库模式,因为我的模式基于Microsoft的ASP.NET成员资格框架(请参阅此相关问题),该模式将字符串规范化为小写.
微软是不是通过告诉我们在C#中使用大写规范化而自相矛盾,而它在Membership表和程序中自己的代码是使用小写规范化吗?我应该将所有内容切换到大写规范化,还是继续使用小写归一化?
[这个问题类似于这一个,但我也有兴趣在沙箱中的可能性.]
我正在考虑在我的C#/ .NET应用程序中嵌入脚本语言,然后将我的一些应用程序API暴露给脚本.似乎有很多好的选择(Lua,Boo,IronPython等),但有没有简单的选项限制脚本语言的内置函数被使用?例如,我不希望脚本能够执行I/O,除非通过我明确公开的API,因此不打印到控制台,打开文件等.这些脚本语言中的任何一种都提供了一种简单的方法这个?
c# ×6
asp.net ×3
scala ×3
asp.net-ajax ×1
clojure ×1
embedded ×1
gridview ×1
leiningen ×1
nhibernate ×1
rhino-mocks ×1
sql-server ×1
tdd ×1
types ×1
unit-testing ×1
updatepanel ×1