【问题标题】:How do I prevent generic arguments from being messed up by VS2008 unit testing如何防止通用参数被 VS2008 单元测试搞砸
【发布时间】:2009-04-16 20:00:46
【问题描述】:

我有两个这样的类(在实际项目中):

namespace app {
    internal class A {
    }

    internal class B {
        private List<A> list;
        private void SomeMethodToTest() {
            list = new List<A>() { new A() };
        }
    }

我的单元测试看起来像

[TestClass()]
public class ATest {
    [TestMethod()]
    public void TestSomeMethod() {
        B_Accessor b = new B_Accessor();
        b.SomeMethodToTest();
        Assert.AreEqual(1, b.list.Count); // ERROR ON THIS LINE
    }
}

在标记的行上,我收到一个 InvalidCastException,说“无法将 System.Collections.Generic.List'1[app.A] 类型的对象转换为 System.Collections.Generic.List'1[app.A_Accessor] ]

问题在于,因为 A 是内部的,所以自动生成的类 B_Accessor 看起来像

[Shadowing("app.B")]
public class B_Accessor : BaseShadow {
    ... stuff ...

    [Shadowing("list")]
    public List<A_Accessor> list { get; set; }

    ... stuff ...
}

请注意,在 Accessor 类中,列表的类型是 List 而不是 List。我已经在应用程序上指定了InternalsVisibleTo属性,所以测试项目可以访问类型A,但是由于某种原因VS将其替换为访问器类型,这使得类型与包装类型不兼容。

除了公开 A 之外,我还能如何解决这个问题?

【问题讨论】:

    标签: visual-studio-2008 unit-testing


    【解决方案1】:

    我已经删除了我之前的答案,因为我没有注意到您已经在使用InternalsVisibleToAttribute

    是什么产生了这些“访问器”类?当您说“VS 用访问器类型替换它”时,您的意思是它会更改您的源代码吗?这听起来很奇怪 - 如果你把它放回去只使用 AB 而不是 A_AccessorB_Accessor 会发生什么?

    如果您可以摆脱自动生成的类,这些自动生成的类意味着看起来像真实的,但不完全一样,那么请摆脱它们。我怀疑这只是一种会导致问题的情况。

    仅使用InternalsVisibleTo 并直接测试内部成员,我从来没有遇到过任何问题。 (嗯,R# 在以前的版本中有时会感到困惑,但除此之外......)

    【讨论】:

    • VS 在构建测试项目时自动生成访问器类。我不能使用 B 代替 B_Accessor,因为我想访问私有成员。
    • 好的,那么如何测试私有方法呢?我不希望打破封装以使测试正常工作。
    • Ick - 我个人会避开自动生成的访问器代码。我通常会尽量避免直接测试想要私有的方法,但如果我,我通常会将它们设为内部。这并不理想,但很务实。
    • 我想是否测试私有方法是一种风格问题。我有一堆填充类内部状态的方法,确定它们是否正确填充状态的唯一合理方法是检查私有成员。
    • 好吧,您必须考虑使用这些访问器类的成本与内部私有方法的封装成本。
    【解决方案2】:

    可以用类似的东西替换测试项目

    internal static class AccessorExtensionMethods {
        internal static List<A> Get_list(this PrivateObject po) {
            return (List<A>)po.GetField("list");
        }
    }
    
    [TestClass()]
    public class ATest {
        [TestMethod()]
        public void TestSomeMethod() {
            PrivateObject bpo = new PrivateObject(new B());
            B_Accessor b = new B_Accessor(bpo);
            b.SomeMethodToTest();
            Assert.AreEqual(1, bpo.Get_list().Count);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-10
      • 2014-02-24
      • 1970-01-01
      • 2021-08-10
      相关资源
      最近更新 更多