反映 Moq 对象会产生 2 个附加属性

发布于 2024-07-29 00:57:43 字数 1017 浏览 4 评论 0原文

我有几种使用反射从一种对象类型转换为另一种对象类型的方法。 我正在通过 Moq 测试转换方法,并且偶然发现了一种我不知道如何处理的行为。 当我反映 Moq 对象以获取 PropertyInfo 时,我得到了两个额外的对象。

  • Moq.Mock``1[Namespace.Class+IElement] Mock
  • Moq.Mock Mock

重现此问题的代码如下:

public void Moq_Reflection() {
    var realElement = new Stuff();

    // Produces 2 items
    PropertyInfo[] pInfo = realElement.GetType().GetProperties(); 

    var mockElement = new Mock<IElement>();
    mockElement.Setup(e => e.Property1).Returns(12);
    mockElement.Setup(e => e.Property2).Returns(42);

    // Produces 4 items
    pInfo = mockElement.Object.GetType().GetProperties();
}

public interface IElement { 
    int Property1 { get; set; } 
    int Property2 { get; set; } 
}

public class Stuff : IElement
{
    public int Property1
    {
        get { return -1; }
        set { }
    }

    public int Property2
    {
        get { return -2; }
        set { }
    }
}

有没有办法反映 Moq 对象并且不检索这些属性?

I've got a couple of methods that use reflection to transform from one object type to another. I'm in the process of testing the transformation methods via Moq and have stumbled upon a behavior I don't know how to handle. When I reflect across a Moq object to obtain PropertyInfo's, I get two additional objects.

  • Moq.Mock``1[Namespace.Class+IElement] Mock
  • Moq.Mock Mock

The code to reproduce this is below:

public void Moq_Reflection() {
    var realElement = new Stuff();

    // Produces 2 items
    PropertyInfo[] pInfo = realElement.GetType().GetProperties(); 

    var mockElement = new Mock<IElement>();
    mockElement.Setup(e => e.Property1).Returns(12);
    mockElement.Setup(e => e.Property2).Returns(42);

    // Produces 4 items
    pInfo = mockElement.Object.GetType().GetProperties();
}

public interface IElement { 
    int Property1 { get; set; } 
    int Property2 { get; set; } 
}

public class Stuff : IElement
{
    public int Property1
    {
        get { return -1; }
        set { }
    }

    public int Property2
    {
        get { return -2; }
        set { }
    }
}

Is there a way to Reflect on a Moq object and not retrieve these properties?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不醒的梦 2024-08-05 00:57:43

今天下午我又思考了这个问题,所以这是另一个想法。

如果我在自己的项目中对此进行编码,我会抽象出对象的反射。 我将创建一个接口,为将返回对象属性的类定义契约,然后创建一个通过使用反射返回属性集来实现该接口的类。 与您可能正在做的事情相同。

但随后在测试中,我将创建接口的新实现,但我会添加所需的任何规则,以过滤掉模拟对象上不需要的属性。 我的实时代码不会包含任何测试所需的代码。

我只是想把这个想法说出来,只是想帮忙。 祝你好运!

I was thinking about this more this afternoon, so here's another idea.

If I were coding this in my own project, I'd abstract out the reflection of the object. I'd create an interface that defines a contract for a class that will return the properties of an object, and then create a class that implements that interface by using reflection to return the set of properties. Same as what you're probably doing.

But then in the tests, I'd create a new implementation of the interface, but I'd add in whatever rules I needed to filter out unwanted properties on my mock objects. My live code wouldn't include any of the code necessary for testing.

I just had to get that idea out, just trying to help. Good luck!

烟柳画桥 2024-08-05 00:57:43

我查看了 LinqPad 中的代码,我找到的删除这两个属性的唯一解决方案是根据 PropertyType 或 Name 是否包含“Mock”来排除它们。 例如:

pInfo.Where(item => item.PropertyType.ToString().Contains("Mock") == false);
pInfo.Where(item => item.Name.Contains("Mock") == false);

它是边缘黑客,但它是我可以找到过滤的唯一属性。 我认为没有办法过滤反射本身。

I took a look at the code in LinqPad, and the only solution I could find to cut those two properties out was to exclude them based on whether PropertyType or Name included "Mock". For example:

pInfo.Where(item => item.PropertyType.ToString().Contains("Mock") == false);
pInfo.Where(item => item.Name.Contains("Mock") == false);

It's borderline hacky, but it's the only attribute I can find to filter. I don't think there's a way to filter the reflection itself.

昔日梦未散 2024-08-05 00:57:43

您可以围绕 Moq 对象创建一个包装器,该包装器实现所需的接口并将属性访问委托给 Moq 对象。 这样,当您反映包装器对象时,您只会看到您感兴趣的属性。

public class ElementWrapper : IElement
{
    private readonly IElement _wrappedElement;

    public ElementWrapper(IElement element)
    {
        _wrappedElement = element;
    }

    public int Property1
    {
        get { return _wrappedElement.Property1; }
        set { _wrappedElement.Property1 = value; }
    }

    public int Property2
    {
        get { return _wrappedElement.Property2; }
        set { _wrappedElement.Property2 = value; }
    }
}

以下是修改 Moq_Reflection() 方法以使用 ElementWrapper 的方法:

public void Moq_Reflection()
{
    var realElement = new Stuff();

    // Produces 2 items
    PropertyInfo[] pInfo = realElement.GetType().GetProperties();

    var mockElement = new Mock<IElement>();
    mockElement.Setup(e => e.Property1).Returns(12);
    mockElement.Setup(e => e.Property2).Returns(42);

    var wrappedElement = new ElementWrapper(mockElement.Object);

    // Produces 2 items
    pInfo = wrappedElement.GetType().GetProperties();
}

You can create a wrapper around the Moq object that implements the desired interface and delegates property access to the Moq object. This way, when you reflect on the wrapper object, you will only see the properties you are interested in.

public class ElementWrapper : IElement
{
    private readonly IElement _wrappedElement;

    public ElementWrapper(IElement element)
    {
        _wrappedElement = element;
    }

    public int Property1
    {
        get { return _wrappedElement.Property1; }
        set { _wrappedElement.Property1 = value; }
    }

    public int Property2
    {
        get { return _wrappedElement.Property2; }
        set { _wrappedElement.Property2 = value; }
    }
}

Here's how you can modify your Moq_Reflection() method to use the ElementWrapper:

public void Moq_Reflection()
{
    var realElement = new Stuff();

    // Produces 2 items
    PropertyInfo[] pInfo = realElement.GetType().GetProperties();

    var mockElement = new Mock<IElement>();
    mockElement.Setup(e => e.Property1).Returns(12);
    mockElement.Setup(e => e.Property2).Returns(42);

    var wrappedElement = new ElementWrapper(mockElement.Object);

    // Produces 2 items
    pInfo = wrappedElement.GetType().GetProperties();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文