Unable to mock Auto Mapper in .Net core - c#

net core 3.1 and I am using auto mapper. I am writing unit test cases and I have below piece of code
var coOrdinateReferenceSystemNames = await _coordinateReferenceSystemRepository.GetAsync(x => x.CoordinateReferenceSystemName.Contains(request.searchName)).ConfigureAwait(false);
IEnumerable<CoordinateReferenceSystemModel> CoordinateReferenceSystemList = _mapper.Map<IEnumerable<CoordinateReferenceSystemModel>>(coOrdinateReferenceSystemNames);
Below is my unit test case.
Func<IEnumerable<CoordinateReferenceSystem>> func = () => { return new List<CoordinateReferenceSystem>() { coordinateReferenceSystemModel }; };
this.mockMapper.Setup(x => x.Map<IEnumerable<CoordinateReferenceSystem>>(It.IsAny<IEnumerable<CoordinateReferenceSystemModel>>())).Returns(func);
Which throws below error
One or more errors occurred. (IMapperBase.Map>([CoordinateReferenceSystem]) invocation failed with mock behavior Strict. All invocations on the mock must have a corresponding setup.)
Can someone help me to understand this error and Which part I am doing wrong here. Any help would be appreciated. Thanks

Hi I have added mock mapper as below and started working fine.
private CoordinateReferenceSystemAr CreateCoordinateReferenceSystemAr()
{
var mockMapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new MappingProfile());
});
var mapper = mockMapper.CreateMapper();
return new CoordinateReferenceSystemAr(this.mockApiRequestHandler.Object,this.mockUnitOfWork.Object, mapper);
}

Related

Test Fail on simulating inserting in database

Please find link to the project source: https://bitbucket.org/danchi/salescheese/src/master/
There I have problem with testing one domain entity
public class RegisterStockUseCaseUnitTests
{
[Fact]
public async void Can_Register_Stock()
{
//arrange
var mockProductRepository = new Mock<IProductRepository>();
var mockStockRepository = new Mock<IStockRepository>();
var mockUserRepository = new Mock<IUserRepository>();
var mockStorageLocationRepository = new Mock<IStorageLocationRepository>();
mockProductRepository.Setup(repo => repo.FindById(It.IsAny<int>()))
.Returns(Task.FromResult(true));
mockUserRepository.Setup(repo => repo.FindById(It.IsAny<string>()))
.Returns(Task.FromResult(true));
mockStorageLocationRepository.Setup(repo => repo.FindById(It.IsAny<int>()))
.Returns(Task.FromResult(true));
var useCase = new RegisterStockUseCase(mockStockRepository.Object,mockProductRepository.Object,mockUserRepository.Object, mockStorageLocationRepository.Object);
var mockOutputPort = new Mock<IOutputPort<RegisterStockResponse>>();
mockOutputPort.Setup(outputPort => outputPort.Handle(It.IsAny<RegisterStockResponse>()));
//act
var response =
await useCase.Handle(new RegisterStockRequest(5, "userId", StockType.Output, UnitOfMeasure.Grams,10,1),
mockOutputPort.Object);
//assert
Assert.True(response);
}
}
When I debug I'm getting: System.NullReferenceException: 'Object reference not set to an instance of an object.'
I can not figure what, can you please help me ?
P.S. Any idea how to improve tests are welcome. All of them are creating with TDD.
Thanks
[Update 1]
Oh I had forgot to setup mocking for creating stock, So I had missing next part of the code
mockStockRepository.Setup(repo => repo.Create(It.IsAny<Stock>()))
.Returns(Task.FromResult(new CreateStockResponse(1, true)));

Mocking Entity Framework Core context

I try to test my app so I need to mock my EF context.
My code seems to be ok, but I have following exception:
"System.ArgumentNullException : Value cannot be null. Parameter name:
source"
Here is my test method:
var options = new DbContextOptionsBuilder<ProductContext>().Options;
var settings = new SqlSettings
{
InMemory = true
};
var context = new Mock<ProductContext>(options, settings);
var mockTreeService = new TreeService(context.Object);
await mockTreeService.CreateTreeAsync("Testing tree", Guid.NewGuid());
context.Verify(x => x.AddAsync(It.IsAny<Tree>(), CancellationToken.None), Times.Once);
It looks like that this exception is thrown during executing this piece of code
var tree = await _context.Trees
.Include(x => x.Translation)
.FirstOrDefaultAsync(x => x.Translation.Pl == name);
It comes from my service which I'm testing
I think this is due to not having a connection string set. Frankly, it's a bit difficult to fully mock out DbContext, which is why the EF Core team has provided an in-memory implementation. This is far easier to work with for testing purposes. Just change your options initialization to:
var options = new DbContextOptionsBuilder<ProductContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
Afterwards, you'll need to populate the database with your test data. Then, you can run the rest of your test.
Note: if you're using the in-memory database, you don't need to mock the context anymore, so you can remove that bit of code. The in-memory database is essentially, itself, a mock.
I have used this https://github.com/huysentruitw/entity-framework-core-mock library. Very easy and can write unit test using less coding.
You can use most of Moq methods if you are using moq framework.
Below is example code for test DBQuerys.
public async Task<Boat> GetByIdAsync(string id)
=> await _boatContext.Boats.Where(x => x.id == id).FirstOrDefaultAsync();
[Fact]
public async Task GetByIdAsync_WhenCalled_ReturnsItem()
{
// Arrange
var models = new[] { new Boat { id = "p1" } };
var dbContextMock = new DbContextMock<BoatContext>();
dbContextMock.CreateDbQueryMock(x => x.Boats, models);
var service = new Properties(dbContextMock.Object);
// Act
var okResult = await service.GetByIdAsync("p1");
// Assert
Assert.IsType<Boat>(okResult.Result);
}
Posting here this may help someone :)
Try to use my Moq/NSubstitute extension MockQueryable: https://github.com/romantitov/MockQueryable
supported all Sync/Async operations
//1 - create a List<T> with test items
var users = new List<UserEntity>()
{
new UserEntity,
...
};
//2 - build mock by extension
var mock = users.AsQueryable().BuildMock();
//3 - setup the mock as Queryable for Moq
_userRepository.Setup(x => x.GetQueryable()).Returns(mock.Object);
//3 - setup the mock as Queryable for NSubstitute
_userRepository.GetQueryable().Returns(mock);
DbSet also supported
//2 - build mock by extension
var mock = users.AsQueryable().BuildMockDbSet();
//3 - setup DbSet for Moq
var userRepository = new TestDbSetRepository(mock.Object);
//3 - setup DbSet for NSubstitute
var userRepository = new TestDbSetRepository(mock);
Note:
AutoMapper supported from 1.0.4 ver
DbQuery supported from 1.1.0 ver
I don't think it's correct to Mock the DbContext. You should be mocking your repositories in your testing... mocking the DbContext is you basically testing Microsoft's code... which is dumb because they already do that. So again... all of your data access should go through repositories (see Repository Pattern) and you should be mocking those in your testing, not the DbContext.

Rhino Mock Test Expected #1, Actual #0 - error

I'm newbie working with Rhino Mock and I'm getting this error that I cannot understand why. Here the test
public void TestGet()
{
var installationReference = new Guid("21D7D135-6E9E-4F92-8313-873CA3ABDCD8");
var study = MockRepository.GenerateMock<IStudy>();
var installation = MockRepository.GenerateMock<IInstallation>();
var license = MockRepository.GenerateMock<ILicense>();
var participant = MockRepository.GenerateMock<IStudyParticipant>();
var clinicalPartner = MockRepository.GenerateMock<IClinicalPartner>();
clinicalPartner.Stub(c => c.FirstName).Return("John");
clinicalPartner.Stub(c => c.LastName).Return("Doe");
installation.Stub(i => i.Reference).Return(installationReference);
license.Stub(l => l.Installations).Return(new List<IInstallation> { installation });
participant.Stub(p => p.Licenses).Return(new List<ILicense> { license });
participant.Stub(p => p.ClinicalPartner).Return(clinicalPartner);
participant.Stub(p => p.ClinicalPartnerStatus).Return(ClinicalPartnerStatus.Active);
study.Stub(s => s.Description).Return("Test WebAPI");
study.Stub(s => s.Participants).Return(new List<IStudyParticipant> { participant });
repository.Stub(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference))))
.Return(new DummyResult<IStudy>(study));
repository.Expect(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference)))).Return(new DummyResult<IStudy>(study)).Repeat.Once();
repository.VerifyAllExpectations();
}
My GetStudiesByInstallationReference.cs
public class GetStudiesByInstallationReference : IQuery<IStudy>
{
public Guid InstallationReference { get; set; }
public GetStudiesByInstallationReference(Guid installationReference)
{
InstallationReference = installationReference;
}
public IQueryResult<IStudy> Execute(ISession session)
{
var criteria = session.CreateCriteria<IStudy>();
criteria.CreateAlias("participants", "p");
criteria.CreateAlias("p.licenses", "l");
criteria.CreateAlias("l.installations", "i");
criteria.Add(Restrictions.Eq("i.Reference", InstallationReference));
criteria.Add(Restrictions.Eq("Status", StudyStatus.Approved));
criteria.Add(Restrictions.Eq("p.ClinicalPartnerStatus", ClinicalPartnerStatus.Active));
criteria.Add(Restrictions.Le("StartDate", DateTime.Now));
criteria.Add(Restrictions.Or(
Restrictions.IsNull("EndDate"),
Restrictions.Gt("EndDate", DateTime.Now)));
return new CriteriaResult<IStudy>(criteria);
}
}
I want to test GetStudiesByInstallationReference was called one time.
What am I doing wrong?...it should pass the test as the Expect clause is the same used in the Stub but I still got the exception
Expected #1, Actual #0.
Anybody could help me with this?
Thanks in advance
I want to test GetStudiesByInstallationReference was called one time.
GetStudiesByInstallationReference is a type, and not a method that you expect to be called.
repository
.Expect(r => r.Query(Arg<GetStudiesByInstallationReference>.Matches(s => s.InstallationReference.Equals(installationReference))))
.Return(new DummyResult<IStudy>(study)).Repeat.Once();
This line from your code is setting up an expectation on the repository mock. It expects that the Query() method is called with a parameter of type GetStudiesByInstallationReference that has the correct installation reference GUID as a property. If this method isn't called with the correct parameter, you will get the error you describe when calling repository.VerifyAllExpectations().
It looks like your test is missing the actual call to the SUT i.e. the "Act" in Arrange/Act/Assert. Simply put, you need to execute some code that will cause the method on your repository to be called as you expect (or change the test).

ReactiveUI: Why do I have to specify the scheduler explicitly in "...Throttle..."when using the TestScheduler

I'm new to ReactiveUI. I have the following simple setup: a path to a csv can be specified and the containing datapoints will be displayed to the user (using oxyplot).
Now I'm trying to test the following subscription:
public GraphViewModel(IScreen hostScreen)
{
HostScreen = hostScreen;
setupGraphFormatting();
// Data Loading if path is valid
this.WhenAnyValue(viewModel => viewModel.PathToDataCsv)
.ObserveOn(RxApp.MainThreadScheduler)
.Throttle(TimeSpan.FromMilliseconds(500), RxApp.TaskpoolScheduler)
.Select(csvPath => csvPath?.Trim('"'))
.Where(csvPath => !string.IsNullOrEmpty(csvPath) && File.Exists(csvPath))
.Subscribe(csvPath =>
{
csvPath = csvPath?.Trim('"');
updatePlotModel(csvPath);
}, exception => {});
/* additional Code*/
}
And that's the corresponding UnitTest:
[Test]
public void If_PathToDataCsv_has_a_valid_value()
{
new TestScheduler().With(scheduler =>
{
string pathToValidCsvFile = "data.log";
var viewModel = new GraphViewModel(null);
scheduler.AdvanceByMs(1000);
viewModel.PathToDataCsv = pathToValidCsvFile;
scheduler.AdvanceByMs(1000);
viewModel.PlotModel.Series.Count.Should().Be(6);
});
}
My first implementation of WhenAnyValue didn't set any of the Schedulers specifically ( in Throttle and lacking any ObserverOn ):
public GraphViewModel(IScreen hostScreen)
{
HostScreen = hostScreen;
setupGraphFormatting();
// Data Loading if path is valid
this.WhenAnyValue(viewModel => viewModel.PathToDataCsv)
.Throttle(TimeSpan.FromMilliseconds(500))
.Select(csvPath => csvPath?.Trim('"'))
.Where(csvPath => !string.IsNullOrEmpty(csvPath) && File.Exists(csvPath))
.Subscribe(csvPath =>
{
csvPath = csvPath?.Trim('"');
updatePlotModel(csvPath);
}, exception => {});
/* additional Code*/
}
But then my Unittest failed. My assumption was that TestScheduler was being used for Throttle behind the scenes and I didn't have to do anything. Am I doing something wrong or is this the right way: If I want to use TestScheduler/TimeTravelâ„¢ I have to specify the schedulers the way I did?
Edit in response to Glenn Watsons answer:
Ok, now it's clear: The methods in question (Throttle, ObserverOn) of course do not use ReactiveUI's Schedulers, because these are methods from the Reactive Extensions Framework. So they can't be replaced implicitly by ReactiveUI in case of a UnitTest except I tell the methods to use the RxApp Schedulers...
RxApp provides the ThreadPoolScheduler when you are in release mode, and the testing scheduler when you are in unit test mode.
By default the reactive extensions (separate to ReactiveUI) will use their own default schedulers which are unaware of unit tests.

Mocking with anonymous parameter

I am trying to Mock my repository layer and I have a method GetSelection(Expression<Func<T, Boolean>> where). I am using Ninjects MickingKernel with Moq to achieve this.
When I do the following, it is fine:
// Create instance of repository
var kernel = new MoqMockingKernel();
var templateRepoMock = kernel.GetMock<ITemplateRepo>();
// Setup mock
templateRepoMock.Setup(x=>x.GetSelection(y=>y.FieldName)
.Returns(new List<Template>() {new Template { ... }));
// Lets pretend that FieldName is a bool!
// Call Service layer
var result = templateService.MyMethod();
// -> Service Layer method
public List<Template> MyMethod()
{
return _templateRepo.GetSelection(x=>x.FieldName);
}
But when I try and add an additional parameter within my expression I get an ArgumentNullExeption:
// Setup mock
templateRepoMock.Setup(x=>x.GetSelection(y=>y.SomeOtherField.Id == 1
&& y.FieldName)
.Returns(new List<Template>() {new Template { ... }));
When I update my service to the following:
public List<Template> MyMethod(SomeObject myObject)
{
return _templateRepo.GetSelection(x=>x.SomeObject.Id == myObject.Id
&& x.FieldName).ToList();
}
It appears to be fine if I update myObject.Id to 1.
Any ideas why this could be happening?
I still don't see the exception that you do, even when using your Github project. Instead, the test fails at the VerifyAll line with this message:
Moq.MockVerificationException : The following setups were not matched:
IProductRepository mock => mock.GetProducts(x => x.Name == "Test" && x.IsActive)
However, I think you may be chasing a red herring, as Moq doesn't support setting up methods that take an Expression. See this answer.

Categories