Mapping always returning null - c#

Line var job = _mapper.Map<DataAccess.Domain.Lab.Job>(jobViewModel); gives error
job variable is always returning null while running the unit test
i have added the mapping for Jobs Profile `
Below is the code:
JobTest.cs class
public class JobTests
{
private static Mock<IMapper> _mapper;
public JobTests()
{
if (_mapper == null)
{
_mapper = new Mock<IMapper>();
_mapper.Setup(x => x.ConfigurationProvider.AssertConfigurationIsValid());
_mapper.Setup(x => x.ConfigurationProvider)
.Returns(
() => new MapperConfiguration(
cfg =>
{
cfg.AddProfile<JobsProfile>();
//cfg.CreateMap<AddJobCommand,JobsProfile > ();
//cfg.CreateMap<JobViewModel, AddJobCommand>();
//cfg.CreateMap<AddJobCommand,JobViewModel>();
}));
}
}
[Fact]
public async Task AddJob_AddSingleEntry()
{
var mapperMock = new Mock<IMapper>();
var data = JobData.AddFakeJobList();
var mockSet = FakeDbSetup.GetMockDbSet<DataAccess.Domain.Lab.Job>(data);
var mockContext = FakeDbSetup.GetMockDbContext();
mockSet.Setup(x => x.AsNoTracking()).Returns(mockSet.Object);
mockContext.Setup(c => c.Jobs).Returns(mockSet.Object);
AddJobCommandHandler handler = new AddJobCommandHandler(mockContext.Object, _mapper.Object);
JobViewModel vm= JobData.AddFakeJobList2();
AddJobCommand command = new AddJobCommand(vm);
//var stubScheduleCommand = new Mock<AddJobCommand>(mockContext.Object);
var job = await handler.Handle(command, new System.Threading.CancellationToken());
Assert.NotNull(job);
}
}
AddJobCommand.cs
public class AddJobCommandHandler : IRequestHandler<AddJobCommand, JobViewModel>
{
private readonly IDrillingFluidsContext _context;
private readonly IMapper _mapper;
public AddJobCommandHandler(IDrillingFluidsContext context, IMapper mapper)
{
(_context, _mapper) = (context, mapper);
}
public async Task<JobViewModel> Handle(AddJobCommand command, CancellationToken cancellationToken)
{
if (command.JobViewModel == null) throw new InvalidOperationException("Empty request.");
var jobViewModel = command.JobViewModel;
try
{
var job = _mapper.Map<DataAccess.Domain.Lab.Job>(jobViewModel);
_context.Set<DataAccess.Domain.Lab.Job>().Add(job);
if (job.Notes!= null)
{
var newNote = job.Notes.FirstOrDefault(n => n.IsNew);
if (newNote != null)
{
newNote.JobId = job.Id;
_context.Set<DataAccess.Domain.Lab.JobNote>().Attach(newNote);
_context.Entry(newNote).State = EntityState.Added;
}
}
if (string.IsNullOrWhiteSpace(job.Name))
{
job.Name = await GenerateJobName(job);
}
await _context.SaveChangesAsync();
jobViewModel.Id = job.Id;
return jobViewModel;
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
catch (DbUpdateException e)
{
throw;
}
catch (Exception e)
{
throw;
}
}
I want the JobViewModel data to be added to the the variable jobs.But it always returns null.This works fine when i am trying to call this method via PostMan.

The problem is that the code uses a mocked mapper that has no setup for the Map method. If there is no setup, the method will return null (for
MockBehavior.Loose`).
If you want the Map method to return a value, you need add a setup, e.g.:
[Fact]
public async Task AddJob_AddSingleEntry()
{
var data = JobData.AddFakeJobList();
var mockSet = FakeDbSetup.GetMockDbSet<DataAccess.Domain.Lab.Job>(data);
var mockContext = FakeDbSetup.GetMockDbContext();
mockSet.Setup(x => x.AsNoTracking()).Returns(mockSet.Object);
mockContext.Setup(c => c.Jobs).Returns(mockSet.Object);
AddJobCommandHandler handler = new AddJobCommandHandler(mockContext.Object, _mapper.Object);
JobViewModel vm= JobData.AddFakeJobList2();
AddJobCommand command = new AddJobCommand(vm);
//var stubScheduleCommand = new Mock<AddJobCommand>(mockContext.Object);
var job = new DataAccess.Domain.Lab.Job()
{
// Initialize job as needed
};
_mapper.Setup(x => x.Map<DataAccess.Domain.Lab.Job>(vm))
.Returns(job);
var job = await handler.Handle(command, new System.Threading.CancellationToken());
Assert.NotNull(job);
}
In the constructor it is not necessary to add setups for the configuration provider if you are using a mocked mapper. So you can setup the _mapper simply like this:
public JobTests()
{
_mapper = new Mock<IMapper>();
}

Related

Mocking AppDBContext (EF Core Db Context) giving null while running unit test case method

I have a service name "DataAccessService". In that service we are calling Procedure and other methods from AppDbContext.
I am writing Unit Test cases for DataAccessService methods. We have method called IsDatabaseUp() which will give response if connection with databases success or not.
When I am trying to access AppDbContext is null which is breaking the unit test method.
DataAccessService:
public bool IsDatabaseUp()
{
try
{
int counter = 1;
while (counter <= EnvConstants.DatabaseCounter)
{
try
{
using (var scope = _serviceScopeFactory.CreateScope())
{
AppDbContext dbContext = scope.ServiceProvider.GetService<AppDbContext>();
//Here dbContext is null
bool isDbUp = dbContext.IsDatabaseUp;
if (isDbUp)
return isDbUp;
counter++;
}
}
catch (Exception ex)
{
counter++;
}
}
}
catch (Exception ex)
{
}
return false;
}
DataServiceTests:
private readonly IDataAccessService _dataAccessService;
private readonly Mock<IServiceScopeFactory> _serviceScopeFactory;
public DataAccessServiceTest()
{
//Arrange
var serviceProvider = new Mock<IServiceProvider>();
serviceProvider
.Setup(x => x.GetService(typeof(AppDbContext)));
var serviceScope = new Mock<IServiceScope>();
serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object);
_serviceScopeFactory = new Mock<IServiceScopeFactory>();
_serviceScopeFactory
.Setup(x => x.CreateScope())
.Returns(serviceScope.Object);
serviceProvider
.Setup(x => x.GetService(typeof(IServiceScopeFactory)))
.Returns(_serviceScopeFactory.Object);
var serviceCollection = new ServiceCollection();
serviceCollection.AddMemoryCache();
var serviceProvider1 = serviceCollection.BuildServiceProvider();
var memoryCache = serviceProvider1.GetService<IMemoryCache>();
var inMemoryCahce= new InMemoryCahce(memoryCache);
_dataAccessService = new DataAccessService(_serviceScopeFactory.Object);
_cacheService = new ServiceOfCahe(inMemoryCahce, _dataAccessService);
LoadMemoryData();
}
[Fact]
public void GetMasterDataInfromationFromSql_Test()
{
var testResult = _dataAccessService.IsDatabaseUp();
}
Can you please help me on this.

this.Clients are disposed SignalR

At the time of the user's connection, everything is going well. When I have a product update (it becomes available for sale), the OnProductStartSales event is called.
But there is one problem, the message does not come to the client because the list of clients in the hub is disposed.
Here is the code of my hub.
public class SalesHub : Hub
{
private readonly ProductDatabaseListener _listener;
public SalesHub(ProductDatabaseListener listener)
{
_listener = listener ?? throw new ArgumentNullException(nameof(listener));
_listener.OnProductStartSales += (s, p) => ProductStartSales(p);
_listener.OnProductDataChanged += (s, p) => ProductDataChanged(p);
}
public async Task ListenProduct(string productId)
{
await this.Groups.AddToGroupAsync(Context.ConnectionId, productId);
}
private async Task ProductStartSales(Product product)
{
await this.Clients.Group(product.Id).SendAsync("StartSales", product.Id);
// await this.Clients.All.SendAsync("StartSales", product.Id);
}
private async Task ProductDataChanged(Product product)
{
await this.Clients.Group(product.Id).SendAsync("DataChanged", product);
}
}
Here is the code of listener.
public class ProductDatabaseListener
{
private readonly IRepository<Product> _repository;
private readonly object _locker = new object();
public ProductDatabaseListener(IServiceProvider serviceProvider)
{
using (var scope = serviceProvider.CreateScope())
{
_repository = scope.ServiceProvider.GetRequiredService<IRepository<Product>>() ?? throw new ArgumentNullException(nameof(_repository));
}
}
public event EventHandler<Product> OnProductStartSales;
public event EventHandler<Product> OnProductDataChanged;
// Need better performance...
public async Task ListenMongo()
{
while (true)
{
var products = await _repository.GetRange(0, int.MaxValue);
var date = DateTime.Now;
List<Task> tasks = new List<Task>();
foreach (var product in products)
{
if (product.IsSalesStart)
{
continue;
}
if (product.StartOfSales <= date)
{
product.IsSalesStart = true;
OnProductStartSales?.Invoke(this, product);
tasks.Add(_repository.Update(product));
}
}
Task.WaitAll(tasks.ToArray());
await Task.Delay(1000);
}
}
}
Here is the client code
"use strict";
var connection = new signalR.HubConnectionBuilder().withUrl("/salesHub").build();
connection.on("ReceiveMessage", function (id) {
var li = document.createElement("li")
document.getElementById("fromHub").appendChild(li)
li.textContent = id;
});
connection.on("startSales", function (id) {
var productId = document.getElementById("objectId").getAttribute("value");
if (productId == id) {
var button = document.getElementById("buy")
button.hidden = false
}
});
connection.logging = true;
connection.start().then(function () {
var productId = document.getElementById("objectId").getAttribute("value");
connection.invoke("ListenProduct", productId).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
}).catch(function (err) {
return console.error(err.toString());
});

Mocking HttpContext

I'm trying to write an Unit Test for my ASP.Net Core application with XUnit framework and MOQ and am trying to test the below method(snippet given below):
public async Task<IActionResult> Save([FromBody] DTO.ContactUs contactUs)
{
contactUs.FirstName = _htmlEncoder.Encode(contactUs.FirstName);
contactUs.LastName = _htmlEncoder.Encode(contactUs.LastName);
contactUs.EmailAddress = _htmlEncoder.Encode(contactUs.EmailAddress);
contactUs.Phone = _htmlEncoder.Encode(contactUs.Phone);
if (HttpContext.User.CurrentClient() != null)
contactUs.ClientId = HttpContext.User.CurrentClient().ClientId;
contactUs.UserId = User.GetUserId();
string dbName = HttpContext.User.CurrentClient().ConnectionString;
var result = _clientService.AddNewContactUs(contactUs, dbName);
if (result)
{
try
{
int clientId = HttpContext.User.CurrentClient().ClientId;
var clientDetails = _clientService.GetClientDetailsByClientID(clientId);
// Lines of code...
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
return Json(result);
}
While I can mock all the other dependent services, I'm kind of stuck with the HttpContext part. I am not able to mock the HttpContext.User.CurrentClient() part where HttpContext.User is of type ClaimsPrincipal and CurrentClient is an user-defined function, defined as:
public static Client CurrentClient(this ClaimsPrincipal principal)
{
if (!string.IsNullOrEmpty(principal.Claims.Single(p => p.Type.Equals(AppClaimTypes.CurrentClient)).Value))
{
int clientId = Convert.ToInt32(principal.Claims.Single(p => p.Type.Equals(AppClaimTypes.CurrentClient)).Value);
return principal.GetClients().Where(c => c.ClientId == clientId).FirstOrDefault();
}
else
{
return null;
}
}
This is my UnitTest class that I have managed to write till now:
public class ContactUsControllerTests
{
private Mock<IClientService> clientServiceMock;
private Mock<IWebHostEnvironment> webHostEnvironmentMock;
private Mock<HtmlEncoder> htmlEncoderObjMock;
private Mock<IEmailNotification> emailNotificationMock;
private Mock<HttpContext> mockContext;
private Mock<HttpRequest> mockRequest;
private Mock<ClaimsPrincipal> mockClaimsPrincipal;
private ContactUs contactUsObj = new ContactUs()
{
FirstName = "TestFN",
LastName = "TestLN",
EmailAddress = "testemail#gmail.com",
Phone = "4564560000",
Comments = "This is just a test"
};
private ClaimsPrincipal principal = new ClaimsPrincipal();
public ContactUsControllerTests()
{
clientServiceMock = new Mock<IClientService>();
webHostEnvironmentMock = new Mock<IWebHostEnvironment>();
htmlEncoderObjMock = new Mock<HtmlEncoder>();
emailNotificationMock = new Mock<IEmailNotification>();
mockRequest = new Mock<HttpRequest>();
mockContext = new Mock<HttpContext>();
// set-up htmlEncoderMock
htmlEncoderObjMock.Setup(h => h.Encode(contactUsObj.FirstName)).Returns(contactUsObj.FirstName);
htmlEncoderObjMock.Setup(h => h.Encode(contactUsObj.LastName)).Returns(contactUsObj.LastName);
htmlEncoderObjMock.Setup(h => h.Encode(contactUsObj.EmailAddress)).Returns(contactUsObj.EmailAddress);
htmlEncoderObjMock.Setup(h => h.Encode(contactUsObj.Phone)).Returns(contactUsObj.Phone);
htmlEncoderObjMock.Setup(h => h.Encode(contactUsObj.Comments)).Returns(contactUsObj.Comments);
// set-up mockContext
mockContext.Setup(m => m.Request).Returns(mockRequest.Object);
mockContext.Object.User.CurrentClient().ClientId = 30; // this throws error
//other initialisations
}
[Fact]
public async void SaveMethodTest()
{
ContactUsController contactUsControllerObj = new ContactUsController(clientServiceMock.Object, webHostEnvironmentMock.Object, htmlEncoderObjMock.Object, emailNotificationMock.Object);
// Act
await contactUsControllerObj.Save(contactUsObj);
// Arrange
// Lines of code
}
}
Any help whatsoever on this would very helpful.

Returning mocked object from partially mocked object not working

I'm writing a unit test where I'm trying to partially mock a service. What I mean is I want one of the methods of the service to return a different mocked object and another method to behave as normal. This is the method I'm testing:
public async Task<List<string>> GetDeletedRecordIds<T>(DateTime startDate)
where T : ISalesForceObject
{
List<string> result;
try
{
var client = await this.GetForceClient();
var init = await client.GetDeleted<DeletedRecordRootObject>(typeof(T).Name, startDate, DateTime.Now);
result = init?.DeletedRecords.Select(d => d.Id).ToList();
}
catch (Exception e)
{
this._logger.LogError(LoggingEvents.GENERAL_ERROR, e, "GetDeletedRecordIds");
throw;
}
return result;
}
This is the method that I need to return a mocked object:
public async Task<IForceClient> GetForceClient()
{
ForceClient forceClient = null;
try
{
var auth = new AuthenticationClient();
var consumerKey = this._settingService.GetSetting("SalesForceConsumerKey");
var consumerSecret = this._settingService.GetSetting("SalesForceConsumerSecret");
var password = this._settingService.GetSetting("SalesForcePassword");
var securityToken = this._settingService.GetSetting("SalesForceSecurityToken");
var username = this._settingService.GetSetting("SalesForceUsername");
var tokenUrl = $"{this._settingService.GetSetting("SalesForceUrl")}/services/oauth2/token";
await auth.UsernamePasswordAsync(
consumerKey,
consumerSecret,
username,
password + securityToken,
tokenUrl);
forceClient = new ForceClient(auth.InstanceUrl, auth.AccessToken, auth.ApiVersion);
}
catch (Exception e)
{
this._logger.LogError(LoggingEvents.GENERAL_ERROR, e, $"GetForceClient");
throw;
}
return forceClient;
}
And this is what I currently have in my unit test:
var mockForceClient = new Mock<IForceClient>();
mockForceClient
.Setup(
i => i.GetDeleted<DeletedRecordRootObject>(
It.IsAny<string>(),
It.IsAny<DateTime>(),
It.IsAny<DateTime>())).ReturnsAsync(deletedRecordRootObject);
var mockService = new Mock<IForceDotComService>();
mockService.Setup(m => m.GetDeletedRecordIds<sf.Account>(It.IsAny<DateTime>()))
.Returns(async (DateTime d) => await this._service.GetDeletedRecordIds<sf.Account>(d));
mockService.Setup(m => m.GetForceClient())
.ReturnsAsync(mockForceClient.Object);
Currently, the test runs in GetDeletedRecordIds until it hits the call to the GetForceClient method. Then instead of returning the mocked ForceClient object, it actually tries to run the method which of course fails.
Thanks in advance for any help.
SOLUTION:
Here's how I solved my problem.
First, I created a service to return the ForceClient as follows:
public class ForceClientService : IForceClientService
{
private readonly ILogger _logger;
private readonly ISettingService _settingService;
public ForceClientService(
ILogger<ForceClientService> logger,
ISettingService settingService)
{
this._logger = logger;
this._settingService = settingService;
}
public async Task<IForceClient> GetForceClient()
{
ForceClient forceClient = null;
try
{
var auth = new AuthenticationClient();
var consumerKey = this._settingService.GetSetting("SalesForceConsumerKey");
var consumerSecret = this._settingService.GetSetting("SalesForceConsumerSecret");
var password = this._settingService.GetSetting("SalesForcePassword");
var securityToken = this._settingService.GetSetting("SalesForceSecurityToken");
var username = this._settingService.GetSetting("SalesForceUsername");
var tokenUrl = $"{this._settingService.GetSetting("SalesForceUrl")}/services/oauth2/token";
await auth.UsernamePasswordAsync(
consumerKey,
consumerSecret,
username,
password + securityToken,
tokenUrl);
forceClient = new ForceClient(auth.InstanceUrl, auth.AccessToken, auth.ApiVersion);
}
catch (Exception e)
{
this._logger.LogError(LoggingEvents.GENERAL_ERROR, e, $"GetForceClient");
throw;
}
return forceClient;
}
}
Then I changed the method I am testing:
public async Task DeleteRecord<TSf>(TSf record)
where TSf : ISalesForceObject
{
try
{
var client = await this._forceClientService.GetForceClient();
var response = await client.DeleteAsync(typeof(TSf).Name, record.Id);
if (!response)
{
throw new Exception($"Error deleting record with ID {record.Id}");
}
}
catch (Exception e)
{
this._logger.LogError(LoggingEvents.GENERAL_ERROR, e, $"ForceDotComService.DeleteRecord");
throw;
}
}
Then I rebuilt my mock to mock the dependencies vs. the methods:
var mockForceClient = new Mock<IForceClient>();
mockForceClient
.Setup(
i => i.GetDeleted<DeletedRecordRootObject>(
It.IsAny<string>(),
It.IsAny<DateTime>(),
It.IsAny<DateTime>())).ReturnsAsync(deletedRecordRootObject);
var mockLogger = new Mock<ILogger<ForceDotComService>>();
var mockForceClientService = new Mock<IForceClientService>();
mockForceClientService.Setup(m => m.GetForceClient()).ReturnsAsync(mockForceClient.Object);
this._service = new ForceDotComService(mockLogger.Object, mockForceClientService.Object);
It is now working as expected. Thanks so much for the help!
Extract this.GetForceClient() out into its own service backed by an abstraction
public IForceClientProvider {
Task<IForceClient> GetForceClient();
}
you would then refactor your current class under test to explicitly depend on that interface via constructor injection.
public class ForceDotComService : IForceDotComService {
private readonly IForceClientProvider provider;
public ForceDotComService(IForceClientProvider provider) {
this.provider = provider;
}
public async Task<List<string>> GetDeletedRecordIds<T>(DateTime startDate)
where T : ISalesForceObject {
List<string> result;
try {
var client = await provider.GetForceClient();
var init = await client.GetDeleted<DeletedRecordRootObject>(typeof(T).Name, startDate, DateTime.Now);
result = init?.DeletedRecords.Select(d => d.Id).ToList();
} catch (Exception e) {
this._logger.LogError(LoggingEvents.GENERAL_ERROR, e, "GetDeletedRecordIds");
throw;
}
return result;
}
}
This would then allow you to mock the desired behavior when testing. In implementation code you would have the same code presented above in the GetForceClient() method.
You mock dependencies, not methods on the class under test.
You need to inject the dependency IForceClient, for example by making it a constructor parameter. Because now your GetForceClient() is simply being called on the class under test, which runs in that class and not on your mock, and so simply returns the new ForceClient() stated in there.

Moq test delete

i'm trying to make a test in my example projet, and i'm getting an error when i assert if the deleted object is null(Assert.IsNull failed).
I'm using Microsoft Visual Studio 2010, Entity Framework 4.3.1 and regular Moq.
Here is the code i'm using:
Service:
private ClientRepository rep;
public ClientService(MyContext ctx)
{
this.rep = new ClientRepository(ctx);
}
public void Delete(Client client)
{
try
{
rep.Delete(client);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
throw new Exception("error");
}
}
public Client GetById(int Id)
{
return rep.GetById(Id);
}
Repository:
private MyContext _dbContext;
public ClientRepository(MyContext ctx)
{
_dbContext = ctx;
}
public void Delete(Client client)
{
Client cl = _dbContext.Clients.Where(x => x.Id == client.Id).FirstOrDefault();
if (cl != null)
{
_dbContext.Clients.Remove(client);
_dbContext.SaveChanges();
}
else
{
throw new Exception("Client does'n exist");
}
}
public Client GetById(int Id)
{
return _dbContext.Clients.Where(x => x.Id == Id).FirstOrDefault();
}
My Delete Test:
[TestMethod]
public void MockDelete()
{
//arrange
var data = new List<Client>
{
new Client(){
Id = 1,
Name = "asdfg"
}
}.AsQueryable();
var dbSetMock = new Mock<IDbSet<Client>>();
var myContextMock = new Mock<MyContext>();
dbSetMock.As<IQueryable<Client>>().Setup(m => m.Provider).Returns(data.Provider);
dbSetMock.As<IQueryable<Client>>().Setup(m => m.Expression).Returns(data.Expression);
dbSetMock.As<IQueryable<Client>>().Setup(m => m.ElementType).Returns(data.ElementType);
dbSetMock.As<IQueryable<Client>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
myContextMock.Setup(m => m.Clients).Returns(dbSetMock.Object);
var service = new ClientService(myContextMock.Object);
//act
var classtodelete = data.First(m => m.Id == 1);
service.Delete(classtodelete);
string name = service.GetById(1).Name;
//assert
dbSetMock.Verify(m => m.Remove(It.IsAny<Client>()), Times.Once());
myContextMock.Verify(m => m.SaveChanges(), Times.Once);
Assert.IsNull(name);
}
My goal is to test the business rules of my Service(i didn't put here), maybe i mocked the wrong classes, or i'm missing something, i hope someone can help me.

Categories

Resources