How can I make an class instance manually of a class that requires an IOptionsMonitor in the constructor?
My Class
private readonly AuthenticationSettings _authenticationSettings;
public ActiveDirectoryLogic(IOptionsMonitor<AuthenticationSettings> authenticationSettings)
{
_authenticationSettings = authenticationSettings.CurrentValue;
}
My test
AuthenticationSettings au = new AuthenticationSettings(){ ... };
var someOptions = Options.Create(new AuthenticationSettings());
var optionMan = new OptionsMonitor(someOptions); // dont work.
ActiveDirectoryLogic _SUT = new ActiveDirectoryLogic(au);
I tried to make an IOptionsMonitor object manually but can't figure out how.
You are calling the constructor of the OptionsMonitor<TOptions> class incorrectly.
In this case I would have just mocked the IOptionsMonitor<AuthenticationSettings> interface
For example using Moq
AuthenticationSettings au = new AuthenticationSettings() { ... };
var monitor = Mock.Of<IOptionsMonitor<AuthenticationSettings>>(_ => _.CurrentValue == au);
ActiveDirectoryLogic _SUT = new ActiveDirectoryLogic(monitor);
Here is another way to do it that doesn't involve trying to set the readonly CurrentValue field.
using Moq;
private IOptionsMonitor<AppConfig> GetOptionsMonitor(AppConfig appConfig)
{
var optionsMonitorMock = new Mock<IOptionsMonitor<AppConfig>>();
optionsMonitorMock.Setup(o => o.CurrentValue).Returns(appConfig);
return optionsMonitorMock.Object;
}
Achieving the same in NSubstitute:
var optionsMonitorMock = Substitute.For<IOptionsMonitor<AuthenticationSettings>>();
optionsMonitorMock.CurrentValue.Returns(new AuthenticationSettings
{
// values go here
});
Related
I have the code below which I would like to test, but I'm not sure whether it is possible or not.
I have EF repositories and they are put together to a class as public properties. I don't know exactly whether it is bad solution or not, but it is easier to manage the code and its dependencies. Only the testability is still a question.
Purpose of my test is injecting data via
administrationRepository.ModuleScreen.GetAll()
method and catch the result. I know that it can be tested once it is deployed, but I want the tests in build time in order to have as fast feedback as possible.
I went through questions and answers here, but I cannot find answers. In my code I got to the point where the property is set up, but when I call the administrationRepoMock.Object.ModuleScreen.GetAll() ReSharper offers only the methods coming from Entitiy Framework and not the Moq related functions.
It is possible what I want? If so, how? Is my design suitable for this? If not can you give me articles, urls where I can see examples?
Repository:
public interface IModuleScreen
{
IEnumerable<DomainModel.Administration.ModuleScreen> GetAll();
}
public interface IAdministrationRepository
{
IModuleScreen ModuleScreen { get; }
}
public partial class AdministrationRepository : IAdministrationRepository
{
public virtual IModuleScreen ModuleScreen { get; private set; }
public AdministrationRepository( IModuleScreen moduleScreen )
{
this.ModuleScreen = moduleScreen;
}
}
Application:
public partial class DigitalLibraryApplication : IDigitalLibraryApplication
{
private IAdministrationRepository _administrationRepository;
private IMapper.IMapper.IMapper _mapper;
private IDiLibApplicationHelper _dilibApplicationHelper;
#region Ctor
public DigitalLibraryApplication( IAdministrationRepository administrationRepository, IMapper.IMapper.IMapper mapper, IDiLibApplicationHelper diLibApplicationHelper)
{
_administrationRepository = administrationRepository;
_mapper = mapper;
_dilibApplicationHelper = diLibApplicationHelper;
}
#endregion
public IEnumerable<ModuleScreenContract> GetModuleScreens()
{
//inject data here
IEnumerable<ModuleScreen> result = _administrationRepository.ModuleScreen.GetAll();
List<ModuleScreenContract> mappedResult = _mapper.MapModuleScreenToModuleScreenContracts(result);
return mappedResult;
}
}
Test code:
[Test]
public void ItCalls_ModuleRepository_Get_Method()
{
List<SayusiAndo.DiLib.DomainModel.Administration.ModuleScreen> queryResult = new List<SayusiAndo.DiLib.DomainModel.Administration.ModuleScreen>()
{
new DomainModel.Administration.ModuleScreen()
{
Id = 100,
},
};
var moduleScreenMock = new Mock<IModuleScreen>();
moduleScreenMock.Setup(c => c.GetAll()).Returns(queryResult);
administrationRepoMock.SetupProperty(c => c.ModuleScreen, moduleScreenMock.Object);
var mapperMock = new Mock<IMapper.IMapper.IMapper>();
var dilibApplicationHerlperMock = new Mock<IDiLibApplicationHelper>();
IDigitalLibraryApplication app = new DigitalLibraryApplication( administrationRepoMock.Object, mapperMock.Object, dilibApplicationHerlperMock.Object );
app.GetModules();
//issue is here
administrationRepoMock.Object.ModuleScreen.GetAll() //???
}
Here is a refactoring of your test that passes when run. You can update the pass criteria to suit you definition of a successful test.
[Test]
public void ItCalls_ModuleRepository_Get_Method() {
// Arrange
List<ModuleScreen> queryResult = new List<ModuleScreen>()
{
new ModuleScreen()
{
Id = 100,
},
};
//Building mapped result from query to compare results later
List<ModuleScreenContract> expectedMappedResult = queryResult
.Select(m => new ModuleScreenContract { Id = m.Id })
.ToList();
var moduleScreenMock = new Mock<IModuleScreen>();
moduleScreenMock
.Setup(c => c.GetAll())
.Returns(queryResult)
.Verifiable();
var administrationRepoMock = new Mock<IAdministrationRepository>();
administrationRepoMock
.Setup(c => c.ModuleScreen)
.Returns(moduleScreenMock.Object)
.Verifiable();
var mapperMock = new Mock<IMapper>();
mapperMock.Setup(c => c.MapModuleScreenToModuleScreenContracts(queryResult))
.Returns(expectedMappedResult)
.Verifiable();
//NOTE: Not seeing this guy doing anything. What's its purpose
var dilibApplicationHerlperMock = new Mock<IDiLibApplicationHelper>();
IDigitalLibraryApplication app = new DigitalLibraryApplication(administrationRepoMock.Object, mapperMock.Object, dilibApplicationHerlperMock.Object);
//Act (Call the method under test)
var actualMappedResult = app.GetModuleScreens();
//Assert
//Verify that configured methods were actually called. If not, test will fail.
moduleScreenMock.Verify();
mapperMock.Verify();
administrationRepoMock.Verify();
//there should actually be a result.
Assert.IsNotNull(actualMappedResult);
//with items
CollectionAssert.AllItemsAreNotNull(actualMappedResult.ToList());
//There lengths should be equal
Assert.AreEqual(queryResult.Count, actualMappedResult.Count());
//And there should be a mapped object with the same id (Assumption)
var expected = queryResult.First().Id;
var actual = actualMappedResult.First().Id;
Assert.AreEqual(expected, actual);
}
I have a simple "Get" method. Ex:
public class Foo : IFoo
{
public Dictionary<string,string> GetSomething(string xyz)
{
var result = new Dictionary<string,string>
... Go to DB and return some key value pairs
return result;
}
}
I wrote a simple test that execute and passes successfully but I'm not getting code coverage on the method.
[TestMethod()]
public void GetSomething()
{
var target = new StubIFoo();
var expected = new Dictionary<string, string>
{
{"blahKey","blahValue"}
};
var results = target.GetSomethingString = s =>
{
var result = new Dictionary<string, string> {{"a", "b"}};
return result;
};
var actual = results("a");
CollectionAssert.AreEqual(expected,actual);
}
I also tried to target the class itself, which provides the coverage but doesn't return any results (ex: "var target = new StubFoo();")
Again, it successfully executes and passes but I'm not getting any coverage. Any pointers would be appreciated. Thanks.
Foo.GetSomething() has 0 code coverage, because you never call it in your test.
Instead, you call StubIFoo.GetSomething().
Change var target = new StubIFoo(); into var target = new Foo();, remove the code initializing StubIFoo and you will get some coverage.
Stubs are there to prevent you from using (and testing) the real class. But you must not use a stub of the class you are testing !
In your test you are not calling the method GetSomething, but instead are setting a value to the property GetSomethingString.
// Here is the problem. This:
var results = target.GetSomethingString = s =>
{
var result = new Dictionary<string, string> {{"a", "b"}};
return result;
};
// Is equal to this:
var lambda = s =>
{
var result = new Dictionary<string, string> {{"a", "b"}};
return result;
};
var results2 = target.GetSomethingString = lambda;
Here is general idea what you should do
public class Foo : IFoo
{
IDbAccess db;
// Pass the interface, do pass parameters to create it inside constructor
public Foo(IDbAccess db)
{
this.db = db;
}
public Dictionary<string,string> GetSomething(string xyz)
{
var result = new Dictionary<string,string>
// ... Go to DB and return some key value pairs
result.Add(db.MethodWhatever(xyz));
return result;
}
}
[TestMethod()]
public void GetSomething()
{
var dbMock = new DatabaseMock(); // This implements IDbAccess
var target = new Foo(dbMock);
var expected = new Dictionary<string, string>
{
{"blahKey","blahValue"}
};
// get something
var results = target.GetSomething("xyzstring");
// verify results
var actual = results.whatever;
CollectionAssert.AreEqual(expected,actual);
}
In Fluent Assertions when comparing objects with DateTime properties there are sometimes a slight mismatch in the milliseconds and the comparison fail. The way we get around it is to set the comparison option like so:
actual.ShouldBeEquivalentTo(expected,
options =>
options.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation))
.WhenTypeIs<DateTime>());
Is there a way to set this up once and have it always apply instead of having to specify it every time we call ShouldBeEquivalentTo?
Update1:
Tried the following approach but it doesn't seem to work, test fails on 1 millisecond difference. The new default does not seem to get called by the factory.
using System;
using FluentAssertions;
using FluentAssertions.Equivalency;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTestProject1
{
class Test
{
public DateTime TestDateTime { get; set; }
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void SettingFluentAssertionDefault()
{
// arrange
var defaultAssertionOptions = EquivalencyAssertionOptions<DateTime>.Default;
EquivalencyAssertionOptions<DateTime>.Default = () =>
{
var config = defaultAssertionOptions();
config.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>();
return config;
};
var testDateTime = DateTime.Now;
var expected = new Test {TestDateTime = testDateTime};
// act
var actual = new Test {TestDateTime = testDateTime.AddMilliseconds(1)};
// assert
actual.ShouldBeEquivalentTo(expected);
}
}
}
Now this can be done with the AssertionOptions static class. To use a simple example:
[TestInitialize]
public void TestInit() {
AssertionOptions.AssertEquivalencyUsing(options => options.ExcludingMissingMembers());
}
Or as in the example above:
AssertionOptions.AssertEquivalencyUsing(options =>
options.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>()
);
Actually, you can. The default configuration factory is exposed by the static property EquivalencyAssertionOptions<Test>.Default. You can easily assign an alternative configuration for a particular data type, or extend the default configuration with additional behavior. Something like:
var defaultAssertionOptions = EquivalencyAssertionOptions<Test>.Default;
EquivalencyAssertionOptions<Test>.Default = () =>
{
var config = defaultAssertionOptions();
config.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation)).WhenTypeIs<DateTime>();
return config;
};
If you want you can get the current default and tuck that away in some variable that you use from your factory method.
I am afraid the closest thing you can come to, is providing new methods
public static void ShouldBeEquivalentToDef<T>(this T subject, object expectation, string reason = "",
params object[] reasonArgs)
{
ShouldBeEquivalentToDef(subject, expectation, config => config, reason, reasonArgs);
}
public static void ShouldBeEquivalentToDef<T>(this T subject, object expectation,
Func<EquivalencyAssertionOptions<T>, EquivalencyAssertionOptions<T>> config, string reason = "", params object[] reasonArgs)
{
var context = new EquivalencyValidationContext
{
Subject = subject,
Expectation = expectation,
CompileTimeType = typeof (T),
Reason = reason,
ReasonArgs = reasonArgs
};
var defConstructedOptions = config(EquivalencyAssertionOptions<T>.Default());
defConstructedOptions.Using<DateTime>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation))
.WhenTypeIs<DateTime>()
new EquivalencyValidator(defConstructedOptions).AssertEquality(context);
}
I have a service layer between my app and the mongo database.
I'm trying to build a unit test using moq
I'm quite new to moq so I started with what I thought would be a trivial test.
Code to test:
public List<BsonDocument> GetAllSettings()
{
var collection = MongoDatabase.GetCollection<BsonDocument>("Settings");
var query = from e in collection.AsQueryable()
select e;
var settings = query.ToList();
return settings;
}
Where:
Settings is a Collection
MongoDatabase is a MongoDBDriver.MongoDatabase
I've tried this as my test:
[Test()]
public void GetAllSettingsTest()
{
//Arrange
BsonDocument doc01 = new BsonDocument();
BsonDocument doc02 = new BsonDocument();
var mongoDatabase = new Mock<MongoDatabase>();
var collection = new Mock<MongoCollection<BsonDocument>>();
mongoDatabase.Setup(f => f.GetCollection(MongoCollection.Settings)).Returns(collection.Object);
collection.Object.Insert(doc01);
collection.Object.Insert(doc02);
ILogger logger = new Logger();
DatabaseClient.DatabaseClient target = new DatabaseClient.DatabaseClient(logger);
target.MongoDatabase = mongoDatabase.Object;
MongoCursor<BsonDocument> cursor = collection.Object.FindAllAs<BsonDocument>();
List<BsonDocument> expected = cursor.ToList();
List<BsonDocument> actual;
//Act
actual = target.GetAllSettings();
//Assert
Assert.AreEqual(expected, actual);
}
I'm getting an error of "Could not find a parameterless constructor" at:
mongoDatabase.Setup(f => f.GetCollection(MongoCollections.Settings)).Returns(collection.Object);
The error refers to the MongoCollection object. I didn't think it had a constructor.
What can I do to get my test to run?
this question is most probably related to: How do I mock MongoDB objects to test my data models?
Anyway, here is minimal Moq configuration required to mock
var message = string.Empty;
var serverSettings = new MongoServerSettings()
{
GuidRepresentation = MongoDB.Bson.GuidRepresentation.Standard,
ReadEncoding = new UTF8Encoding(),
ReadPreference = new ReadPreference(),
WriteConcern = new WriteConcern(),
WriteEncoding = new UTF8Encoding()
};
var server = new Mock<MongoServer>(serverSettings);
server.Setup(s => s.Settings).Returns(serverSettings);
server.Setup(s => s.IsDatabaseNameValid(It.IsAny<string>(), out message)).Returns(true);
var databaseSettings = new MongoDatabaseSettings()
{
GuidRepresentation = MongoDB.Bson.GuidRepresentation.Standard,
ReadEncoding = new UTF8Encoding(),
ReadPreference = new ReadPreference(),
WriteConcern = new WriteConcern(),
WriteEncoding = new UTF8Encoding()
};
var database = new Mock<MongoDatabase>(server.Object, "test", databaseSettings);
database.Setup(db => db.Settings).Returns(databaseSettings);
database.Setup(db => db.IsCollectionNameValid(It.IsAny<string>(), out message)).Returns(true);
var mockedCollection = collection.Object;
Anyway, as I mentioned in linked question, this might not be useful when any of inner-workings of MongoDriver change.
I'm not familiar with the MongoDbDriver.MongoDatabase, but if it works like I think it does, then you can't mock it directly. You need to abstract the MongoDB access code, and mock that. That would be an actual unit test. e.g.
public interface IMongoDBRepository
{
Collection<T> GetCollection<T>(string name) where T BsonDocument;
}
public class MongoDbRepository : IMongoDBRepository
{
public Collection<T> GetCollection<T>(string name)
where T : BsonDocument
{
return MongoDatabase.GetCollection<BsonDocument>(name);
}
}
Now, in your code, you inject an IMongoDBRepository (using whatever DI method you like) and your code would looks something like this:
private IMongoDBRepository _mongoDBRepository; //this gets injected
public List<BsonDocument> GetAllSettings()
{
var collection = _mongoDBRepository.GetCollection<BsonDocument>("Settings");
var query = from e in collection.AsQueryable()
select e;
var settings = query.ToList();
return settings;
}
And finally your unit test:
[Test()]
public void GetAllSettingsTest()
{
//Arrange
BsonDocument doc01 = new BsonDocument();
BsonDocument doc02 = new BsonDocument();
var mongoDatabase = new Mock<IMongoDBRepository>();
var collection = new Mock<MongoCollection<BsonDocument>>();
mongoDatabase.Setup(f => f.GetCollection(MongoCollection.Settings)).Returns(collection.Object);
collection.Object.Insert(doc01);
collection.Object.Insert(doc02);
//rest of test
}
I am trying to experiment with RhinoMocks, where I have to say I am a newbie and probably I don't get some obvious thing here. What I'm doing is something like :
[TestMethod]
public void SaveResponsibleUserFromChangeset()
{
var action = mocks.StrictMock<GenomeAction>();
var changeset = new ActionChangeset();
changeset.ResponsibleUser = new ChangeableProperty<UserIdentity>("Administrator") {IsChanged = true};
changeset.MarkAll(true);
using(mocks.Record())
{
Expect.Call(action.ResponsibleUser).SetPropertyAndIgnoreArgument();
}
using(mocks.Playback())
{
var persistor = new ActionPersistor(new MockIdentityResolver());
persistor.SaveActionChanges(changeset, action);
}
action.VerifyAllExpectations();
}
private class MockIdentityResolver : IIdentityResolver
{
public GenomeUser GetUser(UserIdentity identity)
{
var user = mocks.DynamicMock<GenomeUser>();
user.Username = identity.Username;
return user;
}
}
The intention is to have a very simple test which checks whether the SaveActionChanges method sets the ResponsibleUser property. As a part of this, it needs to resolve the user identity using the resolver, for which I have provided a mock implementation. Unfortunately, it seems I can't just return back another mock within the Playback mode, because it says (on the closing bracket of the second using) that The action is invalid when the object (of type GenomeUser) is in record state.
Any ideas of what is causing the trouble and how to overcome it ?
I think you need to create you new MockIdentityResolver() outside the mocks.Playback().
[TestMethod]
public void SaveResponsibleUserFromChangeset()
{
var action = mocks.StrictMock<GenomeAction>();
var changeset = new ActionChangeset();
var identityResolver;
changeset.ResponsibleUser = new ChangeableProperty<UserIdentity>("Administrator") {IsChanged = true};
changeset.MarkAll(true);
using(mocks.Record())
{
Expect.Call(action.ResponsibleUser).SetPropertyAndIgnoreArgument();
identityResolver = new MockIdentityResolver()
}
using(mocks.Playback())
{
var persistor = new ActionPersistor(identityResolver);
persistor.SaveActionChanges(changeset, action);
}
action.VerifyAllExpectations();
}
private class MockIdentityResolver : IIdentityResolver
{
public GenomeUser GetUser(UserIdentity identity)
{
var user = mocks.DynamicMock<GenomeUser>();
user.Username = identity.Username;
return user;
}
}
you should look at using the AAA syntax, it seems to be generally accepted that it's a clearer way of using stuff.