How to setup Mock to already present object as defaul behavior? - c#

I can do this:
var alreadyPresentMyClass = GetMyClass();//retrieving MyClass from somewhere
var mock = new Mock<IMyClass>();
mock.Setup(x=> x.Method1()).Callback(alreadyPresentMyClass.Method1);
mock.Setup(x=> x.Method2()).Callback(alreadyPresentMyClass.Method2);
....
mock.Setup(x=> x.Method666()).Throws(new Exception("BAD LUCK")); //this is only method which is throwing error in this test. So the only one I want to setup.
....
mock.Setup(x=> x.Method1000()).Callback(alreadyPresentMyClass.Method1000);
How one can remove unnecessary garbage of setuping thousands of methods, and instead setup it based on another object as default, like this:
var mock = Mock.CreateByAlreadyPresent(GetMyClass());
mock.Setup(x=> x.Method666()).Throws(new Exception("BAD LUCK"));
Any thoughts? I can write reflection method myself, but is there already such method?

You would use the property CallBase for that:
var mock = new Mock<MyClass> { CallBase = true };
mock.Setup(x => x.Method666()).Throws(new Exception("BAD LUCK"));
The other methods will have their default behaviour.

Related

XUnit how to mock IMemoryCache ASP.NET Core

I understand IMemoryCache.Set is an extension method so it can not be mocked. People have provided workarounds to such situation e.g as one by the NKosi here. I am wondering how I can achieve that for my data access layer where my MemoryCache returns a value and when not found it gets data from the db, set it to the MemoryCache and return the required value.
public string GetMessage(int code)
{
if(myMemoryCache.Get("Key") != null)
{
var messages= myMemoryCache.Get<IEnumerable<MyModel>>("Key");
return messages.Where(x => x.Code == code).FirstOrDefault().Message;
}
using (var connection = dbFactory.CreateConnection())
{
var cacheOptions = new MemoryCacheEntryOptions { SlidingExpiration = TimeSpan.FromHours(1) };
const string sql = #"SELECT Code, Message FROM MyTable";
var keyPairValueData = connection.Query<KeyPairValueData>(sql);
myMemoryCache.Set("Key", keyPairValueData, cacheOptions );
return keyPairValueData.Where(x => x.Code == code).FirstOrDefault().Message;
}
}
Following is my Unit Test - And off course it is not working as I can't mock IMemoryCache
[Fact]
public void GetMessage_ReturnsString()
{
//Arrange
// Inserting some data here to the InMemoryDB
var memoryCacheMock = new Mock<IMemoryCache>();
//Act
var result = new DataService(dbConnectionFactoryMock.Object, memoryCacheMock.Object).GetMessage(1000);
//assert xunit
Assert.Equal("Some message", result);
}
The first thing I would say is why not use a real memory cache? It would verify the behavior much better and there's no need to mock it:
// Arrange
var memCache = new MemoryCache("name", new NameValueCollection());
//Act
var result = new DataService(dbConnectionFactoryMock.Object, memCache).GetMessage(1000);
// Assert: has been added to cache
memCache.TryGetValue("Key", out var result2);
Assert.Equal("Some message", result2);
// Assert: value is returned
Assert.Equal("Some message", result);
If you really want to mock it out, here's a guide on how to do that:
Because it's an extension method, you need to make sure that it can be called as is. What happens in your case is that the extension method will call into the mock. Since you provide no expected behavior, it will probably fail.
You need to look at the code for the extension method, check what it accesses and then ensure that your mock complies with the expected behavior. The code is available here:
https://github.com/aspnet/Caching/blob/master/src/Microsoft.Extensions.Caching.Abstractions/MemoryCacheExtensions.cs#L77
This is the code:
public static TItem Set<TItem>(this IMemoryCache cache, object key, TItem value, MemoryCacheEntryOptions options)
{
using (var entry = cache.CreateEntry(key))
{
if (options != null)
{
entry.SetOptions(options);
}
entry.Value = value;
}
return value;
}
So, from that, you can see that it accesses CreateEntyand expects an object from it. Then it calls SetOptions and assigns Value on the entry.
You could mock it like this:
var entryMock = new Mock<ICacheEntry>();
memoryCacheMock.Setup(m => m.CreateEntry(It.IsAny<object>())
.Returns(entryMock.Object);
// maybe not needed
entryMock.Setup(e => e.SetOptions(It.IsAny<MemoryCacheEntryOptions>())
...
When you do this, the extension method will be called on the mock and it will return the mocked entry. You can modify the implementation and make it do whatever you want.

Is it a good practice to mock Automapper in unit tests?

There is this codebase where we use automapper and have 2 layers, Domain and Service. Each has its object for data representation, DomainItem and ServiceItem. The service gets data from domain, the uses constructor injected automapper instance to map
class Service
{
public ServiceItem Get(int id)
{
var domainItem = this.domain.Get(id);
return this.mapper.Map<DomainItem, ServiceItem>(domainItem);
}
}
Assume best practices, so mapper has no side-effects and no external dependencies. You'd write a static function to convert one object to another within seconds, just mapping fields.
With this in mind, is it a good practice to mock the mapper in unit tests like this?
[TestClass]
class UnitTests
{
[TestMethod]
public void Test()
{
var expected = new ServiceItem();
var mockDomain = new Mock<IDomain>();
// ... setup
var mockMapper = new Mock<IMapper>();
mockMapper.Setup(x => x.Map<DomainItem, ServiceItem>(It.IsAny<DomainItem>()))
.Returns(expected);
var service = new Service(mockDomain.Object, mockMapper.Object);
var result = service.Get(0);
Assert.AreEqual(expected, result);
}
}
To me, it seems that such unit test does not really bring any value, because it is effectively testing only the mocks, So i'd either not write it at all OR I'd use the actual mapper, not the mocked one. Am I right or do I overlook something?
I think the issue here is that the test is badly written for what it is actually trying to achieve which is testing Service.Get().
The way I would write this test is as follows:
[TestMethod]
public void Test()
{
var expected = new ServiceItem();
var mockDomain = new Mock<IDomain>();
var expectedDomainReturn = new DomainItem(0); //Illustrative purposes only
mockDomain.Setup(x => x.DomainCall(0)).Returns(expectedDomainReturn); //Illustrative purposes only
var mockMapper = new Mock<IMapper>();
mockMapper.Setup(x => x.Map<DomainItem, ServiceItem>(It.IsAny<DomainItem>()))
.Returns(expected);
var service = new Service(mockDomain.Object, mockMapper.Object);
var result = service.Get(0);
mockDomain.Verify(x => x.DomainCall(0), Times.Once);
mockMapper.Verify(x => x.Map<DomainItem, ServiceItem>(expectedDomainReturn), Times.Once);
}
This test instead of not really checking the functionality of the service.Get(), checks that the parameters passed are correct for the individual dependency calls based on the responses. You are thus not testing AutoMapper itself and should not need to.
Checking result is basically useless but will get the code coverage up.

How do I get arguments passed to a data access layer that uses System.Action as an input parameter?

I'm trying to create some unit tests for an application I've recently inherited. Currently using NSubstitute because that's what the previous programmer used, but I'm not attached to it.
The method I'm testing calls the DataService class' Create method.
Calling Create Method
var contactProductLink = this.dsService.Create<ContactProductLink>(x =>
{
x.ContactRoleId = prod.RoleId;
x.ContactId = contactViewModel.ContactId;
x.ProductId = prod.ProductId;
x.Active = true;
x.InsertDate = DateTime.Now;
x.InsertUserId = user.employeeId;
x.UpdateDate = DateTime.Now;
x.UpdateUserId = user.employeeId;
});
DataService Create Method:
public TEntity Create<TEntity>(Action<TEntity> propertySetter = null) where TEntity : class
{
var tEntity = this.Context.Create<TEntity>();
if (propertySetter != null)
{
propertySetter(tEntity);
}
return tEntity;
}
The approach I've taken (and maybe there's a better way) is to use NSubstitute to mock the DataService. When I'm doing my assertions at the end, I'm checking to make sure that the Create method was called:
mockDataSupplierService.Received().Create<ContactProductLink>(Arg.Any<Action<ContactProductLink>>());
However, I'd like to also verify the input that was sent to the method is correct, and here's where I'm running into trouble. I can get the System.Action object that was passed to the Create method, but I can't figure out how to pull out the parameters (such as ContactRoleId, ContactId, etc. as posted in the calling create method code snippet).
So after all of that what I'm asking is:
How can I access those input parameters so I can verify the correct arguments are being passed to the data service? Is it even possible?
Is there a better way to do this than what I'm currently trying to do?
Solution
//Arrange
mockDataSupplierService.Create<ContactProductLink>(Arg.Do<Action<ContactProductLink>>(x=> actionToPopulateEntity = x));
//Assert
mockDataSupplierService.Received().Create<ContactProductLink>(Arg.Any<Action<ContactProductLink>>());
var entity = new ContactProductLink();
actionToPopulateEntity.Invoke(entity);
Assert.AreEqual(ExpectedContactId, entity.ContactId);
How can I access those input parameters so I can verify the correct arguments are being passed to the data service? Is it even possible?
Essentially you can't, as it is not possible to extract "code" details from action (consider what happens when you pass an action that doesn't set any properties - this is totally legal, but would break hypothetical mechanism).
However, you can try this instead:
Create entity with initial values
Use Arg.Invoke argument, telling NSubstitute to use chosen object as action parameter
Verify that entity properties values changed
For example:
// Arrange
var entity = new ContactProductLink
{
ContactRoleId = // ...
// ...
};
mockDataSupplierService
.Create<ContactProductLink>(Arg<ContactProductLink>.Invoke(entity));
// Act
// ...
Assert.That(entity.ContactRoleId, Is.EqualTo(2));
// ...

Moq.Setup not returning expected collection?

I have the following code:
var service = new Mock<INavigationService>();
service.Setup(x => x.GetSchemes(new SchemeFilterEntity())).Returns(new List<SchemeEntity>
{
new SchemeEntity
{
Id = 1,
Name = "Test"
},
new SchemeEntity
{
Id = 2,
Name = "Test 2"
}
});
var sut = service.Object;
var sut = service.GetSchemes(new SchemeFilterEntity());
However when the GetSchemes method is called it returns null?
Any ideas?
I believe that should be
service.Setup(x => x.GetSchemes(It.IsAny< SchemeFilterEntity >())).Returns.....
because otherwise, moq will be looking for that exact instance of the 'new SchemeFilterEntity()' that you passed in in the setup method, which will never match anything else.
Edit: That said, your sut should not be the thing you are mocking, it should be the thing that's using your mocked object.
I don't know what you are tring to test but if you want "Override" the behavior of GetSchema
using a mocked object that method must be virtual on the class
If you want to use the mocked object to stub out the INavigationService you have to do the below
.........
var sut = service.Object;
SomeThing.UseNavigavtionService(sut); //this is supposed to be the class which you will test.Sut is a mocked INavigationService
in your setup you should also use It.IsAny< SchemeFilterEntity >() instead of create a concrete object

The right way to mock (with moq) methods that return mocked objects?

Which of these is correct?
var mockLogger = new Mock<EntLibLogger>();
mockLogger.Setup(i => i.CreateTracer(It.IsAny<string>()))
.Returns((string operationName) =>
{
var mockTracer = new Mock<EntLibTracer>(operationName);
mockTracer.Setup(i => i.IsTracingEnabled())
.Returns(true);
mockTracer.CallBase = true;
return mockTracer.Object;
});
mockLogger.CallBase = true;
//EntLibLogger.Current is a singleton that is shared across multiple threads.
//This Initialize method will set EntLibLogger.Current to the mocked instance
//instead of the default (non-mocked) configuration
EntLibLogger.Initialize(mockLogger.Object);
OR
var mockTracer = new Mock<EntLibTracer>(operationName);
mockTracer.Setup(i => i.IsTracingEnabled())
.Returns(true);
mockTracer.CallBase = true;
var mockLogger = new Mock<EntLibLogger>();
mockLogger.Setup(i => i.CreateTracer(It.IsAny<string>()))
.Returns(mockTracer.Object);
mockLogger.CallBase = true;
EntLibLogger.Initialize(mockLogger.Object);
I believe the first approach is correct but I am not sure if Moq might be doing some magic under the hood and just wanted to validate :)
I guess the main question is what you want to happen if it calls CreateTracer twice. In the first version you'll get two different mock tracers; in the second you'll get the same one twice.
The second version is what I've usually used in jMock, EasyMock and Rhino.Mocks - but I don't have any experience with Moq, so it may be more idiomatic to use the first form there. The second is simpler though, IMO :)

Categories

Resources