如何模拟 Autofac.Multitenant.MultitenantContainer.ConfigureTenant

问题描述

我有一个看起来像这样的代码

private readonly ITenantProvdier _tenantProvider;

//ctor ...

public void ConfigureNewTenants( MultitenantContainer multiTenantContainer )
{
    var tenants = _tenantProvider.GetNewTenantsToAdd(); //gets tenants that are just added during the runtime.
    
    foreach( var tenant in tenants )
    {
        try
        {
            multiTenantContainer.ConfigureTenant( tenant.Id,someCustomAction);
        }
        catch( ArgumentNullException exception )
        {
            // log error and do smth
        }
        catch( InvalidOperationException exception )
        {
            // log error and do smth
        }
    }
}

我的目标是测试 multiTenantContainer 抛出 ArgumentNullExceptionInvalidOperationException 时的代码行为。

我正在使用 NUnit 和 Moq。 并尝试做下一个

var containerMock = new Mock<MultitenantContainer>();
containerMock
  .Setup(c => c.ConfigureTenant(It.IsAny<object>,It.IsAny<Action<ContainerBuilder>>)
  .Thows(someException);

但它不起作用,因为方法 ConfigureTenant 有下一个签名:public void ConfigureTenant(object tenantId,Action<ContainerBuilder> configuration)。并且不能模拟非虚拟类方法

我尝试使用 virtual new 方法创建派生类。它没有帮助。

解决方法

伙计。在您的示例中,您将收到这样的错误:

Unsupported expression: c => c.ConfigureTenant(It.IsAny<object>(),It.IsAny<Action<ContainerBuilder>>())
Non-overridable members (here: MultitenantContainer.ConfigureTenant) may not be used in setup / verification expressions.

Moq 说他不能模拟非虚方法。 我们有解决方案吗? - 是的!

您需要从方法中提取 interface 并模拟它或将方法标记为 virtual。在您的情况下,最好选择 interface 选项。 让我们试试吧!


我尝试创建类似于您的示例:

  1. 在接口中包装方法
    public interface IConfigureNewTenants
    {
        void ConfigureNewTenants(MultitenantContainer multiTenantContainer,int id,Action<ContainerBuilder> action);
    }
  1. 为其创建实现
    public class NewTenats : IConfigureNewTenants
    {
        public void ConfigureNewTenants(MultitenantContainer multiTenantContainer,Action<ContainerBuilder> action)
        {
            multiTenantContainer.ConfigureTenant(id,action);
        }
    }
  1. 模拟方法
            // Arrnage
            configureNewTenantsMock
                .Setup(x => x.ConfigureNewTenants(multitenantContainer.Object,It.IsAny<int>(),It.IsAny<Action<ContainerBuilder>>()))
                .Throws<InvalidOperationException>();
  1. 并进行测试!
            // Act
            Action act = () => manager.ConfigureNewTenants(multitenantContainer.Object);

            // Assert
            act.Should().Throw<InvalidOperationException>()
                .And.Message
                .Should().Be("InvalidOperationExceptionMessage");
  1. 运行测试 Test

这是解决问题的主要思路。 完整的解决方案有更多的代码行,这是我为它创建的方式 gist

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...