C# 需要帮助改进功能性指挥系统的体系结构吗
给定一组可以并发调用Execute()方法的命令,是否有方法对命令类进行单元测试,以确保代码的其他维护者不会添加成员数据(传递给构造函数的只读成员除外) 例如: 代码启动时,在脚本操作和可为操作提供服务的命令之间创建映射:C# 需要帮助改进功能性指挥系统的体系结构吗,c#,concurrency,async-await,C#,Concurrency,Async Await,给定一组可以并发调用Execute()方法的命令,是否有方法对命令类进行单元测试,以确保代码的其他维护者不会添加成员数据(传递给构造函数的只读成员除外) 例如: 代码启动时,在脚本操作和可为操作提供服务的命令之间创建映射: actionCommandTable = [“Translate”, new TranslateCommand(appcontext)], [“Scale”, new ScaleCommand(appcontext)], [“Assignment” new Assignme
actionCommandTable =
[“Translate”, new TranslateCommand(appcontext)],
[“Scale”, new ScaleCommand(appcontext)],
[“Assignment” new AssignmentCommand(appcontext, expressionEvaluator)]
然后在运行时:
actionCommandTable[“Translate”].Execute(actionDataContext);
“转换”命令:
public class TranslateAction : ActionCommand {
//read-only interface
private readonly AliasProvider aliasMap;
//bad - need to prevent this instance from being added - will be overwritten unexpectedly
private int transientValue;
public TranslateAction(IAppContext appContext) {
aliasMap = appContext.AliasMap;
}
public override async Task Execute(ActionDataContext actionDataContext) {
//assign to transientValue
//do some work
//await an animation
//do more work
//read from transientValue
}
}
在本例中,如果Execute在共享成员上不起作用,那么Execute中的所有工作都是正常的
actionDataContext旨在成为瞬态状态完整数据的目标。您可以使用反射来确保所有字段和属性都是只读的。但是,为了验证分配是否正确,您可能必须根据需求验证命令值分配
public void ValidateAllFieldsAreInitOnly(Type sut)
{
foreach(var field in sut.GetFields(BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.Public))
{
Assert.IsTrue(field.IsInitOnly);
}
foreach (var property in sut.GetProperties(BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.Public))
{
// returns true if the property has a set accessor, even if the accessor is private, internal
Assert.IsFalse(property.CanWrite);
// OR can use depending on requirement
// The MethodInfo object representing the Set method for this property if the set accessor is public, or null if the set accessor is not public.
Assert.IsNull(property.GetSetMethod());
}
}
请注意,当有人将属性声明为只读,但以错误的方式初始化它时,这不会捕获场景-
测试将为绿色
public class GoodCommand
{
private readonly string privateField1;
private readonly string privateField2;
public GoodCommand(string field1, string field2)
{
privateField1 = field1;
privateField2 = field2;
}
}
测试将捕获(红色)
对于这种情况,测试是绿色的,因为适当的分配检查可能会根据需求而变化。您还可以通过验证分配的值是否如预期的那样来捕获此场景
public class SmartBadCommand
{
private readonly string privateField1;
private readonly string privateField2;
public SmartBadCommand(string field1)
{
privateField1 = field1;
privateField2 = "testingbadCommand";
}
}
希望有帮助。您可以使用反射来确保所有字段和属性都是只读的。但是,为了验证分配是否正确,您可能必须根据需求验证命令值分配
public void ValidateAllFieldsAreInitOnly(Type sut)
{
foreach(var field in sut.GetFields(BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.Public))
{
Assert.IsTrue(field.IsInitOnly);
}
foreach (var property in sut.GetProperties(BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.Static |
BindingFlags.Public))
{
// returns true if the property has a set accessor, even if the accessor is private, internal
Assert.IsFalse(property.CanWrite);
// OR can use depending on requirement
// The MethodInfo object representing the Set method for this property if the set accessor is public, or null if the set accessor is not public.
Assert.IsNull(property.GetSetMethod());
}
}
请注意,当有人将属性声明为只读,但以错误的方式初始化它时,这不会捕获场景-
测试将为绿色
public class GoodCommand
{
private readonly string privateField1;
private readonly string privateField2;
public GoodCommand(string field1, string field2)
{
privateField1 = field1;
privateField2 = field2;
}
}
测试将捕获(红色)
对于这种情况,测试是绿色的,因为适当的分配检查可能会根据需求而变化。您还可以通过验证分配的值是否如预期的那样来捕获此场景
public class SmartBadCommand
{
private readonly string privateField1;
private readonly string privateField2;
public SmartBadCommand(string field1)
{
privateField1 = field1;
privateField2 = "testingbadCommand";
}
}
希望有帮助。这听起来比单元测试更适合使用Roslyn分析器。这听起来比单元测试更适合使用Roslyn分析器。