【问题标题】:Proper use of internal class when testing with generic base test class使用通用基础测试类进行测试时正确使用内部类
【发布时间】:2019-03-22 08:44:40
【问题描述】:

TL;DR 我似乎无法让 InternalsVisibleTo 使用我的单元测试

背景

我目前正在开发一个库,我想在其中创建一些(但不是全部)类,以避免混淆用户。只有某些类应该从该 dll 中公开。

我认为这将是一个学习如何处理 C# 中的 internal 关键字的好项目。

每当我创建一个新项目时,我发现自己使用的是 DDD 的变体,我会将职责分成不同的 DLL,但是为了这个问题,请考虑一下我的项目结构(从上到下) ):

  • 使用我的库的可执行文件
  • 我正在开发的库
  • 用于对我的库进行单元测试的单元测试库
  • 测试工具库,包含所有单元测试的基类

有关架构的工作示例,您可以查看我在 github 上的 HelloWorld project。这个例子并没有复制这里的问题,它只是用来说明我通常如何分层我的代码。

我会经常为我的单元测试创​​建一个基类,为我正在测试的任何类型创建模拟,即这个例子:

public class TestsFor<TInstance> where TInstance : class
{
    protected MoqAutoMocker<TInstance> AutoMock { get; set; }
    protected TInstance Instance { get; set; }

    public TestsFor()
    {
        AutoMock = new MoqAutoMocker<TInstance>();

        RunBeforeEachUnitTest(); // virtual

        Instance = AutoMock.ClassUnderTest;

        RunAfterEachUnitTest(); // virtual
    }
}

问题

我编写的单元测试通常采用以下形式:

public class ReportServiceTests : TestsFor<ReportService>
{
    [Fact]
    public async Task CreateReport_WhenCalled_LogsTheCall()
    {
        // Act
        await Instance.CreateReport();

        // Assert            
        GetMockFor<ILogger>().Verify(logger => logger.Enter(Instance, nameof(Instance.CreateReport)), Times.Once());
    }
}

每个单元测试将派生 TestsFor 类,以便为我提供一个开箱即用的模拟测试类。但是,即使我用 InternalsVisibleTo 标记了我的内部类,将它们指向单元测试程序集以及测试工具程序集(单元测试基类所在的位置),我仍然得到不一致的可访问性错误。

有谁知道如何解决这个问题?

【问题讨论】:

  • 根据您的模拟库的工作方式,它可能会即时创建程序集,并且这些程序集可能还需要使用 InternalsVisibleTo 进行标识。希望它使用一致的名称!
  • 您使用的是哪个模拟库?
  • 如果您使用的是起订量,请添加此[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
  • 我使用 Moq 作为模拟库
  • 你能不测试内部吗?仅测试公共类,内部将通过它们进行测试。

标签: c# unit-testing


【解决方案1】:

您遇到的问题是您正在尝试创建一个比其基类更易于访问的类。

您可以委托而不是派生:

public class ReportServiceTests
{
    private Tests tests = new Tests();

    [Fact]
    public async Task CreateReport_WhenCalled_LogsTheCall()
    {
        tests.CreateReport_WhenCalled_LogsTheCall();
    }

    private class Tests : TestsFor<ReportService>
    {
        public async Task CreateReport_WhenCalled_LogsTheCall()
        {
            // Act
            await Instance.CreateReport();

            // Assert            
            GetMockFor<ILogger>().Verify(logger => logger.Enter(Instance, nameof(Instance.CreateReport)), Times.Once());
        }
    }
}

【讨论】:

    猜你喜欢
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 2022-08-18
    • 2013-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多