While unit testing using Moq, I get the following error:
Message: System.NotSupportedException :
Invalid setup on non-virtual (overridable in VB) member:
cm => cm.AppSettings[It.IsAny<string>()]
Per these findings, I understand that it's preferable to use abstract classes or interfaces with Moq.
- Why does the property I want to mock need to be virtual?
- Moq is throwing Invalid setup on a non-overridable member, when class is in Service Project
- Invalid setup on a non-virtual (overridable in VB) member
- Moq: Invalid setup on a non-overridable member: x => x.GetByTitle(“asdf”)
In short, I've done my homework. =)
But what if I'm actually using an interface?
ConfigurationServiceTests
[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; }
}
ConfigurationService
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";
}
Why have I created the IConfigurationManager
interface?
In addition to it, I want to bind it directly using Ninject, in my production code. So I need no concrete implementation of the interface, hence my big surprise with the above-mentioned exception.
kernel.Bind<IConfiguration>().To<ConfigurationManager>().InSingletonScope();
And doing so allows me to unit test my ConfigurationService
.
Any idea?