使用 Moq 模拟内部类以进行单元测试

问题描述 投票:0回答:2

假设我有一个类“ClassA”,它依赖于类“ClassB”(注入到 ClassA 的构造函数中)。我想模拟 ClassB,以便可以单独测试 ClassA。两个课程都是内部课程。

如果我错了,请纠正我,但看起来 Moq 只能模拟一个公共类,它有一个公共无参数构造函数,并且要模拟的方法是

public virtual
。我真的不想让这些课程公开。我是否错过了起订量的某些内容,或者它只是不适合我想做的事情?

我想我可以创建一个 ClassB 实现的接口(比如“IClassB”),将其注入到 ClassA 中,然后模拟该接口。 ClassB 仍然可以是内部的(尽管我意识到接口方法必须是公共的)。虽然这可行,但我对创建大量接口感到不安,这些接口的唯一目的是支持单元测试模拟。想法?

unit-testing mocking moq
2个回答
75
投票

您可以通过在项目的 assembly.cs

 中添加 
InternalsVisibleToAttribute 来使内部结构对 Moq 可见,如下所示:

[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

为什么是

"DynamicProxyGenAssembly2"
而不是
"Moq"
?它是为包含动态生成的代理类型而创建的动态程序集的名称(所有这些都由另一个库Castle 的 DynamicProxy 处理),Moq 使用该动态程序集。因此,您将类型暴露给动态代理程序集,而不是 Moq 本身。

但是,如果没有可重写的成员,模拟类有什么意义呢?您不会模拟任何内容,所有调用都将使用实际实现。你的第二个解决方案,

我想我可以创建一个 ClassB 实现的接口(比如“IClassB”),将其注入到 ClassA 中,然后模拟该接口。

这是我通常会做的。它的目的不仅仅是“支持单元测试模拟” - 它可以帮助您构建松散耦合的组件,这始终是值得追求的目标。


2
投票

此外,您可以将其添加到

.csproj
文件中。

<ItemGroup>
  <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
  <_Parameter1>DynamicProxyGenAssembly2</_Parameter1>
  </AssemblyAttribute>
</ItemGroup>
© www.soinside.com 2019 - 2024. All rights reserved.