两个具有相同AssemblyQualifiedName的不同类?

时间:2018-08-21 11:08:15

标签: c# exception reflection mstest type-mismatch

在MSTest项目中,我声明了一些测试的内部类。像这样在测试项目的命名空间中声明:

namespace Körningar.Test.Hjälpklasser
{
    internal interface ITestkörningParams { int Heltal { get; } string Text { get; } }
    internal class TestkörningParams : ITestkörningParams { public int Heltal { get; set; } public string Text { get; set; } }
    // ...
}

在一种经过测试的方法中,我有一个此类parms的实例,并遍历其属性以记录其值:

// Create parms of type körningsparametrarKlass.
object parms = paramhämtare.HämtaParametrar(args, körningsparametrarKlass);

// Log the property values of the parms object.
log.Info($"Körningsparametrar:\r\n"
    + string.Join("\r\n",
        körningsparametrarKlass.GetProperties()
        .Where(pi => pi.GetGetMethod() != null)
        .Select(pi
          => $"{pi.Name} = {Convert.ToString(pi.GetGetMethod().Invoke(parms, null))}")
    )
);

此行代码会引发TargetException,并显示一条消息,指出该对象与目标类型不匹配。

paramhämtare.HämtaParametrar创建的方法来自NSubstitute模拟对象,该对象执行以下操作:

paramhämtareMock.HämtaParametrar(new string[] { }, null).ReturnsForAnyArgs(new TestkörningParams());

对于从körningsparametrarKlass提取的属性获取器,parms对象可能是错误的类型,这与为parms对象实例化的类型相同。

在VS Watch窗口中检查变量将得出以下信息:

Dump from VS 2017 Watch window

如您所见,parms对象和körningsparametrarKlass类型的AssemblyQualifiedName相同,但是实际类型的对象不同(在转储中标记)。据我所知,类型对象应该使用==具有可比性,但是我也用körningsparametrarKlass.Equals(parms.GetType())测试了相同的结果。还要注意,即使有些行是灰色的,“监视”窗口中的所有行实际上也是最新的-我在进行转储之前刷新了所有行。

这怎么会发生,我该如何解决?

我还应该提到,只有当我在同一解决方案中同时为此测试项目和另一个测试项目运行测试时,这似乎才发生。如果我只运行有问题的测试,或者包含该测试的整个测试项目,那么也不例外。

[编辑] 在我看来,当从测试的程序集中的AssemblyQualifiedName派生Type对象时,可能会出现问题。此类型对象显然与测试程序集中调用的typeof(TheClass)不同。而且仅当我同时为该测试程序集和另一个程序集运行测试时,才会出现此问题。关于所讨论的类型,这些程序集之间不应有任何名称甚至命名空间冲突。

1 个答案:

答案 0 :(得分:0)

我想我找到了问题的原因。

我有两个测试程序集,我们称它们为Test1Test2,它们分别包含程序集Ass1Ass2的测试。

Test1引用了Test2Test2包含一个名为TheClass的内部类。

Ass2中,某些代码使用程序集限定名称来获取表示Type的{​​{1}}对象。

问题在于,此时TheClass有两个“版本”:TheClass中的一个“版本”和Test2中包含的一个“版本”,因为该程序集引用了Test1

因此,显然Test2对象代表了Type的对象,而Test1内部对TheClass的引用显然代表了Test2的对象。 / p>

让我惊讶的是,运行Test2测试时,测试框架实际上将加载Test1程序集。应该发生这种情况,并且可以避免吗?