I'm very comfortable using AutoFixture.Freeze<Mock<IViolationChecker>>() to setup a class for testing with .Verify() and .Setup().
However, in the class I'm working on takes an enumerable of IViolationChecker
private readonly IEnumerable<IViolationChecker> _violationCheckers;
How can I use AutoFixture.Freeze to define my list of IViolationChecker? I've used
var violationCheckers = AutoFixture.Freeze<Mock<IEnumerable<IViolationChecker>>>();
But I'm not sure how I would write the .Verify() or .Setup().
An option would be to freeze the collection and use Mock.Get for each item to get the mocks for setup and verification.
//Arrange
var violationCheckers = AutoFixture.Freeze<IEnumerable<IViolationChecker>>();
var mocks = violationCheckers.Select(item => Mock.Get(item));
foreach (var mock in mocks) {
mock.Setup(_ => _.SomethingHere()).Verifiable(); //setup mock as desired.
}
//...
//Act
//...exercise member under test
//Assert
foreach(var mock in mocks) {
mock.Verify(_ => /* some predicate*/, Times.Once);
//OR
//mock.Verify();
}
//...
Related
I want to migrate from MVVM Light to Microsoft Toolkit MVVM and I have a problem with my unit tests.
I don't know how properly wrap IMessengerExtensions and IMessenger to use it in unit testing.
Example of test I have in my project:
public void LoadingFinishedTest()
{
var messengerMock = new Mock<IMessenger>();
messengerMock.Setup(mock => mock.Send(It.Is<IsLoadingMessage>()));
var testedViewModelMock = new Mock<SomeViewModel>(messengerMock.Object);
testedViewModelMock.Object.LoadingFinished();
messengerMock.Verify(mock => mock.Send(It.Is<IsLoadingMessage>(), Times.Once);
}
And of course if I do not wrap anything and just try to run test I get:
System.NotSupportedException : Type to mock must be an interface, a delegate, or a non-sealed, non-static class.
Assuming SomeViewModel is het subject under test, an actual instance of this should be used to exercise the test case
public void LoadingFinishedTest() {
// Arrange
var messengerMock = new Mock<IMessenger>();
messengerMock.Setup(mock => mock.Send(It.Is<IsLoadingMessage>()));
var subject = new SomeViewModel(messengerMock.Object);
// Act
subject.Object.LoadingFinished();
// Assert
messengerMock.Verify(mock => mock.Send(It.Is<IsLoadingMessage>(), Times.Once);
}
The verification can also be configured during setup
For example
public void LoadingFinishedTest() {
// Arrange
var messengerMock = new Mock<IMessenger>();
messengerMock
.Setup(mock => mock.Send(It.Is<IsLoadingMessage>()))
.Verifiable(); //<-- NOTE THIS
var subject = new SomeViewModel(messengerMock.Object);
// Act
subject.Object.LoadingFinished();
// Assert
messengerMock.Verify(); //<-- verifying expected behavior that was setup
}
I also ran into problems with this. For me the issue was that IMessenger.Send<TMessage> is an extension method. Unfortunately, as I've learned, Moq cannot mock extension methods because they are static.
My solution was to create an IMessengerWrapper which can be mocked:
// Mockable interface
public interface IMessengerWrapper
{
TMessage Send<TMessage>(TMessage message)
where TMessage : class;
}
// Real implementation for actual code
public class MessengerWrapper : IMessengerWrapper
{
private IMessenger _messenger;
public MessengerWrapper(IMessenger messenger)
{
_messenger = messenger;
}
public TMessage Send<TMessage>(TMessage message)
where TMessage : class
{
return _messenger.Send(message);
}
}
Which can then be used in place of IMessenger in your unit tests, e.g.:
public void LoadingFinishedTest()
{
var messengerMock = new Mock<IMessengerWrapper>();
// Using It.IsAny here because It.Is requires a predicate
messengerMock.Setup(mock => mock.Send(It.IsAny<IsLoadingMessage>()));
var testedViewModelMock = new Mock<SomeViewModel>(messengerMock.Object);
testedViewModelMock.Object.LoadingFinished();
messengerMock.Verify(mock => mock.Send(It.IsAny<IsLoadingMessage>(), Times.Once);
}
Sources:
How do I use Moq to mock an extension method?
Mocking Static Methods for Unit Testing
My MongoDbRepository has an interface called IRepository. So I am mocking the interface to set up the method which is UpdateOneAsync. However my MerchantConfigurationRepository can only take a MongoDbRepository object which is why I need to cast it. For some reason when I do this
(MongoDBRepository<MerchantConfigurationEntity>)dataAccess.Object
I get the error
Unable to cast object of type 'Castle.Proxies.IRepository`1Proxy' to
type 'Newgistics.Common.MongoDb.MongoDBRepository`1
How am I supposed to set up the Mock and then pass in the object, I tried setting a variable to the dataAccess.Object and passing in that variable, but if I do that the setup goes in as null.
Below you will find the unit test:
[Fact]
public async void UpdateMerchantSuccessPushesMerchantEntityToDataStore()
{
//Arrange
var originalMerchantConfig = ModelFactory.GetMerchant();
var merchants = new List<MerchantConfigurationEntity>();
var dataAccess = new Mock<IRepository<MerchantConfigurationEntity>>();
dataAccess.Setup(m => m.UpdateOneAsync(It.IsAny<MerchantConfigurationEntity>()))
.Callback((MerchantConfigurationEntity m) => merchants.Add(m))
.Returns(Task.FromResult(1));
var merchantRepo = new MerchantConfigurationRepository((MongoDBRepository<MerchantConfigurationEntity>)dataAccess.Object);
//Act
var result = await merchantRepo.UpdateMerchant(originalMerchantConfig);
//Assert
result.ShouldNotBeNull();
result.Sucess.ShouldBeTrue();
merchants.Count.ShouldBe(1);
merchants[0].merchantId.ShouldBe(originalMerchantConfig.merchantId);
}
Your classes should be dependent on abstractions and not on concretions for this very reason. MerchantConfigurationRepository should be dependent on IRepository<MerchantConfigurationEntity> and not the implementation MongoDBRepository<MerchantConfigurationEntity>
public class MerchantConfigurationRepository {
private readonly IRepository<MerchantConfigurationEntity> repository;
public MerchantConfigurationRepository(IRepository<MerchantConfigurationEntity> repositiry) {
this.repository = repository;
}
//...other code
public Task<int> UpdateMerchant(Merchant model) { ... }
}
That way now you have more flexibility to use the mocked repository when testing in isolation.
var merchantRepo = new MerchantConfigurationRepository(dataAccess.Object);
Just make sure that your DI knows to use the actual implementation in production.
I want mock lazy interface but I got object reference not set to an instance of an object exception.
Here is class under test:
public class ProductServiceService : IProductServiceService
{
private readonly Lazy<IProductServiceRepository> _repository;
private readonly Lazy<IProductPackageRepository> _productPackageRepository;
public ProductServiceService(
Lazy<IProductServiceRepository> repository,
Lazy<IProductPackageRepository> productPackageRepository)
{
_repository = repository;
_productPackageRepository = productPackageRepository;
}
public async Task<OperationResult> ValidateServiceAsync(ProductServiceEntity service)
{
var errors = new List<ValidationResult>();
if (!await _productPackageRepository.Value.AnyAsync(p => p.Id == service.PackageId))
errors.Add(new ValidationResult(string.Format(NameMessageResource.NotFoundError, NameMessageResource.ProductPackage)));
.
.
.
return errors.Any()
? OperationResult.Failed(errors.ToArray())
: OperationResult.Success();
}
}
and here is test class
[Fact, Trait("Category", "Product")]
public async Task Create_Service_With_Null_Financial_ContactPerson_Should_Fail()
{
// Arrange
var entity = ObjectFactory.Service.CreateService(packageId: 1);
var fakeProductServiceRepository = new Mock<Lazy<IProductServiceRepository>>();
var repo= new Mock<IProductPackageRepository>();
repo.Setup(repository => repository.AnyAsync(It.IsAny<Expression<Func<ProductPackageEntity, bool>>>()));
var fakeProductPackageRepository = new Lazy<IProductPackageRepository>(() => repo.Object);
var sut = new ProductServiceService(fakeProductServiceRepository.Object, fakeProductPackageRepository);
// Act
var result = await sut.AddServiceAsync(service);
// Assert
Assert.False(result.Succeeded);
Assert.Contains(result.ErrorMessages, error => error.Contains(string.Format(NameMessageResource.NotFoundError, NameMessageResource.ProductPackage)));
}
fakeProductPackageRepository always is null. I followed this blog post but still I'm getting null reference exception.
How to mock lazy initialization of objects in C# unit tests using Moq
Update:
here is a screen that indicates fakeProductPackageRepository is null.
Here is a refactored version of your example:
[Fact, Trait("Category", "Product")]
public async Task Create_Service_With_Null_Financial_ContactPerson_Should_Fail() {
// Arrange
var entity = ObjectFactory.Service.CreateService(packageId = 1);
var productServiceRepositoryMock = new Mock<IProductServiceRepository>();
var productPackageRepositoryMock = new Mock<IProductPackageRepository>();
productPackageRepositoryMock
.Setup(repository => repository.AnyAsync(It.IsAny<Expression<Func<ProductPackageEntity, bool>>>()))
.ReturnsAsync(false);
//Make use of the Lazy<T>(Func<T>()) constructor to return the mock instances
var lazyProductPackageRepository = new Lazy<IProductPackageRepository>(() => productPackageRepositoryMock.Object);
var lazyProductServiceRepository = new Lazy<IProductServiceRepository>(() => productServiceRepositoryMock.Object);
var sut = new ProductServiceService(lazyProductServiceRepository, lazyProductPackageRepository);
// Act
var result = await sut.AddServiceAsync(service);
// Assert
Assert.False(result.Succeeded);
Assert.Contains(result.ErrorMessages, error => error.Contains(string.Format(NameMessageResource.NotFoundError, NameMessageResource.ProductPackage)));
}
UPDATE
The following Minimal, Complete, and Verifiable example of your stated issue passes when tested.
[TestClass]
public class MockLazyOfTWithMoqTest {
[TestMethod]
public async Task Method_Under_Test_Should_Return_True() {
// Arrange
var productServiceRepositoryMock = new Mock<IProductServiceRepository>();
var productPackageRepositoryMock = new Mock<IProductPackageRepository>();
productPackageRepositoryMock
.Setup(repository => repository.AnyAsync())
.ReturnsAsync(false);
//Make use of the Lazy<T>(Func<T>()) constructor to return the mock instances
var lazyProductPackageRepository = new Lazy<IProductPackageRepository>(() => productPackageRepositoryMock.Object);
var lazyProductServiceRepository = new Lazy<IProductServiceRepository>(() => productServiceRepositoryMock.Object);
var sut = new ProductServiceService(lazyProductServiceRepository, lazyProductPackageRepository);
// Act
var result = await sut.MethodUnderTest();
// Assert
Assert.IsTrue(result);
}
public interface IProductServiceService { }
public interface IProductServiceRepository { }
public interface IProductPackageRepository { Task<bool> AnyAsync();}
public class ProductServiceService : IProductServiceService {
private readonly Lazy<IProductServiceRepository> _repository;
private readonly Lazy<IProductPackageRepository> _productPackageRepository;
public ProductServiceService(
Lazy<IProductServiceRepository> repository,
Lazy<IProductPackageRepository> productPackageRepository) {
_repository = repository;
_productPackageRepository = productPackageRepository;
}
public async Task<bool> MethodUnderTest() {
var errors = new List<ValidationResult>();
if (!await _productPackageRepository.Value.AnyAsync())
errors.Add(new ValidationResult("error"));
return errors.Any();
}
}
}
A Lazy<> as a parameter is somewhat unexpected, though not illegal (obviously). Remember that a Lazy<> wrapped around a service is really just deferred execution of a Factory method. Why not just pass the factories to the constructor? You could still wrap the call to the factory in a Lazy<> inside your implementation class, but then you can just fake / mock your factory in your tests and pass that to your sut.
Or, perhaps the reason that you're passing around a Lazy<> is because you're really dealing with a singleton. In that case, I'd still create a factory and take dependencies on the IFactory<>. Then, the factory implementation can include the Lazy<> inside of it.
Often, I solve the singleton requirement (without the lazy loading) via setting a custom object scope for the dependency in my IoC container. For instance, StructureMap makes it easy to set certain dependencies as singleton or per-request-scope in a web application.
I rarely need to assert that I've done a lazy initialization on some service inside of a system-under-test. I might need to verify that I've only initialized a service once per some scope, but that's still easily tested by faking the factory interface.
The thing is that you are creating a Mock of Lazy as fakeProductServiceRepository and later on are returning that instance where just a Mock is needed.
You should change
var fakeProductServiceRepository = new Mock<Lazy<IProductServiceRepository>>();
to
var fakeProductServiceRepository = new Mock<IProductServiceRepository>();
I am trying to test a repository using MOQ to mock the behavior of the repo. I am failry new to MOQ, so bear with me please.
Given the following method:
public static SubmissionVersion DeleteNote(IRepository repository, SubmissionVersion version, Guid noteId)
{
Note note = repository.GetById<Note>(noteId);
version.Notes.Remove(note);
repository.Save(version);
repository.Delete(note);
return repository.GetById<SubmissionVersion>(version.Id);
}
Does this test look OK?
[Fact]
public void DeleteNoteV2()
{
// Arrange
var note = new Note{ Id = Guid.NewGuid()};
var subVersion = new Mock<SubmissionVersion>();
subVersion.Setup(x => x.Notes.Remove(note));
var repo = new Mock<IRepository>();
repo.Setup(x => x.GetById<Note>(note.Id)).Returns(note);
repo.Setup(x => x.GetById<SubmissionVersion>(It.IsAny<Guid?>())).Returns(subVersion.Object);
// Act
SubmissionVersion.DeleteNote(repo.Object, subVersion.Object, note.Id.Value);
// Assert
repo.Verify(x => x.GetById<Note>(note.Id), Times.Once());
repo.Verify(x => x.Save(subVersion.Object), Times.Once());
repo.Verify(x => x.Delete(note), Times.Once());
subVersion.Verify(x => x.Notes.Remove(It.IsAny<Note>()), Times.Once());
}
Your approach is good, however I would adjust few things. I have made few changes to your test and mocking components which you can see below.
Unit Test
You method under test within your Unit Test (see below), does not really match with the method which you have defined in your question.
Unit test method call:
SubmissionVersion.DeleteNote(repo.Object, subVersion.Object, note.Id.Value);
Method under test:
public static SubmissionVersion DeleteNote
(IRepository repository, SubmissionVersion version, Guid noteId)
I assume the above method is part of another class, I called it as NotesHelper - Not the ideal name for repository calls, but it is just to get the compilation working.
I would personally separate out your Unit test into 2 separate Unit tests. One to verify whether the required methods being called, and the other is to verify whether the notes have been removed from the collection.
Also instead of creating a mocked SubmissionVersion, I created a fakeSubmissionVersion.
This is because the routines within SubmissionVersion may not be mockable. You can also do a state based testing (preferred) to ensure the version.Notes.Remove(note); has been called.
[Fact]
public void DeleteNote_Deletion_VerifyExpectedMethodsInvokecOnlyOnce()
{
// Arrange
var note = new Note { Id = Guid.NewGuid() };
var fakeSubmissionVersion = new SubmissionVersion() { Notes = new List<Note>() };
var repo = new Mock<IRepository>();
repo.Setup(x => x.GetById<Note>(It.IsAny<Guid>())).Returns(note);
// Act
NotesHelper.DeleteNote(repo.Object, fakeSubmissionVersion, note.Id.Value);
// Assert
repo.Verify(x => x.GetById<Note>(note.Id), Times.Once());
repo.Verify(x => x.Save(fakeSubmissionVersion), Times.Once());
repo.Verify(x => x.Delete(note), Times.Once());
}
The above test can be further improved by defining each Verification in its own test.
[Fact]
public void DeleteNote_Deletion_VerifyDeleteMethodCalledOnlyOnce()
This way if one the test fails we would know exactly which method has not been called with the expectation. Sometimes, having multiple verifications as above can be problematic. For example, if the Save method has not been called, you would never know the Delete method has been called or not. This is because the exception has been thrown when the Save method has not been called and the test execution has been terminated.
This would result in multiple tests but they are more readable and maintainable. Of course you can refactor the common code into a factory or helper method.
[Fact]
public void DeleteNote_RemoveNotes_ReturnsExpectedNotes()
{
// Arrange
var note = new Note { Id = Guid.NewGuid() };
var fakeSubmissionVersion = new SubmissionVersion() { Notes = new List<Note>() { note } };
var repo = new Mock<IRepository>();
repo.Setup(x => x.GetById<Note>(It.IsAny<Guid>())).Returns(note);
// Act
NotesHelper.DeleteNote(repo.Object, fakeSubmissionVersion, note.Id.Value);
// Assert
Assert.AreEqual(0, fakeSubmissionVersion.Notes.Count);
}
Additional Note: Also providing a descriptive Unit test method names improves the readability of the Unit Tests.
I have the following method on my repository interface:
IQueryable<T> GetQuery<T>(Expression<Func<T, bool>> predicate) where T : class;
I have a class I'm going to act on in a unit test with the following constructor:
public MyClass(IUnitOfWork unitOfWork)
On IUnitOfWork Interface there is an exposed Repository property:
Repository Repository { get; }
So I'm trying to unit test the MyClass.DoSomething() method like so:
[TestInitialize]
public void Setup()
{
accounts = new List<Account>()
{
new Account()
{
Id = 123
}
};
}
Next I have the unit test Arrange section which is failing:
//Arrange
var repositoryMock = new Mock<IUnitOfWork>();
repositoryMock.Setup(x => x.Repository.GetQuery<Account>(y => y.Id == 123))
.Returns(accounts.AsQueryable()); //This setup always fails
var myClass = new MyClass(repositoryMock.Object); //don't even get here
The exception I get is:
System.NotSupportedException: Invalid setup on a non-virtual
(overridable in VB) member: x => x.Repository.GetQuery(y =>
y.Id == 123)
I've tried other variations of the Setup on the mock:
repositoryMock.Setup(x => x.Repository.GetQuery<Account>()).Returns((Account a) => accounts.AsQueryable().Where(z => z.Id == 123));
and
repositoryMock.Setup(x => x.Repository.GetQuery<Account>(y => y.Id == 123)).Returns((Account a) => accounts.AsQueryable().Where(z => z == a));
But to no success; I get the identical exception each time. They always throw the same exception when I run the unit test. Since I am using an Interface to be mocked, why am I getting this exception and how do I do this properly? Thanks!
Instead of your current setup try this:
//Arrange
var repositoryMock = new Mock<IUnitOfWork>();
repositoryMock.Setup(x => x.Repository.GetQuery<Account>(
It.IsAny<Expression<Func<T, bool>>>());
.Returns(accounts.AsQueryable()); // This should not fail any more
var myClass = new MyClass(repositoryMock.Object);
In reality, you do not need to pass any concrete lambda because you are returning your list either way.
The Repository property you have shown is not of an interface type. It's some concrete class. And as the error message tells you, you cannot define expectations on non virtual methods. So what you should do instead is to work with an abstraction if you want to be able to mock it:
IRepository Repository { get; }