gpt4 book ai didi

c# - 非虚拟成员的无效设置 - 在接口(interface)上?

转载 作者:太空狗 更新时间:2023-10-29 23:07:31 26 4
gpt4 key购买 nike

在使用 Moq 进行单元测试时,出现以下错误:

Message: System.NotSupportedException : 
Invalid setup on non-virtual (overridable in VB) member:
cm => cm.AppSettings[It.IsAny<string>()]

根据这些发现,我了解到在 Moq 中使用抽象类或接口(interface)更可取。

总之,我已经完成了作业。 =)

但如果我实际使用的是一个界面呢?

配置服务测试

[TestFixture]
public class ConfigurationServiceTests {
[Test]
public void DialectShouldQueryConfigurationManagerAppSettings() {
// Given
configurationManagerMock
.Setup(cm => cm.AppSettings[It.IsAny<string>()])
.Returns(It.IsAny<string>());

// When
var dialect = configurationService.Dialect;

// Then
dialect.Should().BeOfType<string>();
configurationManagerMock.Verify(cm => cm.AppSettings[It.IsAny<string>()]);
}

[SetUp]
public void ConfigurationServiceSetUp() {
configurationManagerMock = new Mock<IConfigurationManager>();
configurationService =
new ConfigurationService(configurationManagerMock.Object);
}

private Mock<IConfigurationManager> configurationManagerMock;
private IConfigurationService configurationService;
}

IConfigurationManager

public interface IConfigurationManager {
NameValueCollection AppSettings { get; }
ConnectionStringSettingsCollection ConnectionStrings { get; }
}

IConfigurationService

public interface IConfigurationService {
string ConnectionDriver { get; }
string ConnectiongString { get; }
string Dialect { get; }
}

配置服务

public class ConfigurationService : IConfigurationService {
public ConfigurationService(IConfigurationManager configurationManager) {
this.configurationManager = configurationManager;
}

public string ConnectionDriver {
get { return configurationManager.AppSettings["ConnectionDriver"]; }
}

public string ConnectionString {
get {
return configurationManager
.ConnectionStrings[ConnectionStringKey]
.ConnectionString;
}
}

public string Dialect {
get { return configurationManager.AppSettings[DialectKey]; }
}

private readonly IConfigurationManager configurationManager;

private const string ConnectionStringKey = "DefaultConnectionString";
private const string DialectKey = "Dialect";
}

为什么要创建 IConfigurationManager 接口(interface)?

除此之外,我想在我的生产代码中使用 Ninject 直接绑定(bind)它。所以我不需要接口(interface)的具体实现,因此我对上述异常感到非常惊讶。

kernel.Bind<IConfiguration>().To<ConfigurationManager>().InSingletonScope();

这样做可以让我对我的 ConfigurationService 进行单元测试。

有什么想法吗?

最佳答案

您正在尝试模拟 NameValueCollection 的索引器而不是你的属性(property) setter/getter 。

你需要做类似的事情(注意 SetupGet 而不是 Setup ):

  .SetupGet(cm => cm.AppSettings).Returns(....)

如果您想要返回“任何东西”的“模拟”集合,您可能需要覆盖实际类(检查是否有可能这样做)。

如果您知道要查找的设置 - 从 Mock 返回已填充的集合可能是一个选项:

 configurationManagerMock  
.SetupGet(cm => cm.AppSettings)
.Returns(new NameValueCollection { {"SettingName", "Value"}});

另一种选择是返回一些自定义界面或 IDictionary<string,string>所以你也可以模拟索引:

interface IConfigurationManager 
{
IDictionary<string,string> AppSettings { get; }
...

关于c# - 非虚拟成员的无效设置 - 在接口(interface)上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23945625/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com