Rog*_*mbe 22 c# attributes unit-testing moq mocking
我正在为我的项目编写命令行界面.用户输入"create project foo",它找到负责"project"的控制器,然后调用该Create方法,将"foo"作为第一个参数传递.
它在很大程度上依赖于属性和反射:控制器看起来像这样:
[ControllerFor("project")]
class ProjectController
{
[ControllerAction("create")]
public object Create(string projectName) { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)
我想在解析器的单元测试中使用Moq,如下所示:
Mock<IProjectsController> controller = new Mock<IProjectsController>();
controller.Expect(f => f.Create("foo"));
parser.Register(controller.Object);
parser.Execute("create project foo");
controller.VerifyAll();
Run Code Online (Sandbox Code Playgroud)
将属性添加到接口似乎不起作用 - 它们不是由派生类继承的.
我可以让Moq为被模拟的类添加属性吗?
Ric*_*lay 32
更新:我刚刚意识到您可以使用TypeDescriptor.AddAttributes实际向现有类型添加属性,可以针对实例或类型执行:
Mock<IRepository> repositoryMock = new Mock<IRepository>();
CustomAttribute attribute = new CustomAttribute();
// option #1: to the instance
TypeDescriptor.AddAttributes(repositoryMock.Object, attribute );
// option #2: to the generated type
TypeDescriptor.AddAttributes(repositoryMock.Object.GetType(), attributes);
Run Code Online (Sandbox Code Playgroud)
如果需要,AddAttribute将返回一个TypeDescriptorProvider,可以将其传递给TypeDescriptor.RemoveProvider以删除之后的属性.
请注意,Attribute.GetCustomAttributes不会以这种方式找到在运行时添加的属性.而是使用TypeDescriptor.GetAttributes.
原始答案
我不相信Moq(或任何其他模拟框架)支持自定义属性.我知道Castle Proxy(通常用于实际创建类的框架)确实支持它,但是没有办法通过Moq访问它.
你最好的办法是将你的属性加载方法抽象为一个接口(接受Type和Attribute类型),然后模拟它.
编辑:例如:
public interface IAttributeStrategy
{
Attribute[] GetAttributes(Type owner, Type attributeType, bool inherit);
Attribute[] GetAttributes(Type owner, bool inherit);
}
public class DefaultAttributeStrategy : IAttributeStrategy
{
public Attribute[] GetAttributes(Type owner, Type attributeType, bool inherit)
{
return owner.GetCustomAttributes(attributeType, inherit);
}
public Attribute[] GetAttributes(Type owner, bool inherit)
{
return owner.GetCustomAttributes(inherit);
}
}
Run Code Online (Sandbox Code Playgroud)
需要属性的类使用IAttributeStrategy的实例(通过IoC容器,或者可选地将其传递给构造函数).通常它将是DefaultAttributeStrategy,但您现在可以模拟IAttributeStrategy以覆盖输出.
这可能听起来很复杂,但添加一层抽象比试图实际模拟属性要容易得多.
| 归档时间: |
|
| 查看次数: |
7009 次 |
| 最近记录: |