C
C#10mo ago
chino

✅ System.NullReferenceException : Object reference not set to an instance of an object.

Hey guys, fairly new to .NET C# here. I'm trying to learn Unit Testing/Mocking at the moment. I found myself stuck on this error for days now that I'm thinking of just skipping it over and move on to another topic, but I really really wanna resolve this issue! I setup a passing test but it's returning me an error 'System.NullReferenceException : Object reference not set to an instance of an object.' I'm so lost here, I've tried everything but nothing worked. Please see photos for reference. I included the method I'm testing, mocking and the test result.
19 Replies
cap5lut
cap5lut10mo ago
u are mocking the IDBContext.GetEmployeeDetails(int) method, but ur EmployeeRepository doesnt even use that method in its GetEmployeeDetails(int) method. u would have to mock everything _context related from this method:
cap5lut
cap5lut10mo ago
but this will be a pain, it would be easier to set up an in-memory db and seed it with the data u need and drop the in-memory db afterwards again basically u would have to mock _context.Employees then on that result u would have to mock .Include(j => j.jobPosition) then on that result u would have to mock .Include(d => d.department) then on that result u would have to mock .Select(emp => new EmployeeDetails(...)) then on that result u would have to mock .Where(e => e.EmployeeId == id) then on that result u would have to mock .FirstOrDefaultAsync() so setting up the in-memory db and adding the data would be quite easier and less error prone
chino
chino10mo ago
does this mean im mocking the wrong method? you're right, i came across in-memory db upon searching for solutions for this problem and it seemed to be the best option for me but i still somehow wanna learn mocking first before i hop on to another topic feels bad skipping it over catsweat
cap5lut
cap5lut10mo ago
basically what would be easy to mock would be the use of ur EmployeeRepository if it implements an interface for example assume this little controller:
[ApiController]
public class EmployeeController {
private readonly IEmployeeRepository _employeeRepository;
public EmployeeController(IEmployeeRepository employeeRepository)
{
_employeeRepository = employeeRepository;
}

[HttpGet]
[Route("/api/employees/{id}/details")]
public async Task<EmployeeDetails?> GetEmployeeDetails(int id)
{
return await _employeeRepository.GetEmployeeDetails(id);
}
}
[ApiController]
public class EmployeeController {
private readonly IEmployeeRepository _employeeRepository;
public EmployeeController(IEmployeeRepository employeeRepository)
{
_employeeRepository = employeeRepository;
}

[HttpGet]
[Route("/api/employees/{id}/details")]
public async Task<EmployeeDetails?> GetEmployeeDetails(int id)
{
return await _employeeRepository.GetEmployeeDetails(id);
}
}
to test this, u would mock the IEmployeeRepository:
[Test]
public async Task GetEmployeeDetails_ReturnsEmployeeDetails()
{
Mock<IEmployeeRepository> mock = new Mock<IEmployeeRepository>();
var employeeDetails = new EmployeeDetails { ... };
mock.Setup(er => er.GetEmployeeDetails(id)).ReturnsAsync(employeeDetails);
var sut = new EmployeeController(mock.Object);
// do test
}
[Test]
public async Task GetEmployeeDetails_ReturnsEmployeeDetails()
{
Mock<IEmployeeRepository> mock = new Mock<IEmployeeRepository>();
var employeeDetails = new EmployeeDetails { ... };
mock.Setup(er => er.GetEmployeeDetails(id)).ReturnsAsync(employeeDetails);
var sut = new EmployeeController(mock.Object);
// do test
}
yes, because u didnt use the IDBContext.GetEmployeeDetails(int) method in ur EmployeeRepository.GetEmployeeDetails(int) method, but the EF core stuff directly. so u would have to mock all of that chain as well it would ofc be totally valid to mock the ef core part, but as shown, its relatively complex, so its time consuming and error prone. so use the right tool for the job especially stateful things and chain calls are not easy to mock. there its sometimes even simplier to implement the interface urself instead of using a mocking library. most of the time u use the latter only for simple stuff, where u dont have to mock much, eg a datetime provider or like the example shown mocking the employee repository itself.
chino
chino10mo ago
yes my EmployeeRepository does implement an interface it looks like this
chino
chino10mo ago
the interface is like this
using ASPMVCNETCRUD.Models;

namespace ASPMVCNETCRUD.Repository
{
public interface IEmployeeRepository
{


Task<IEnumerable<EmployeeDetails>> GetEmployeeRecords();
Task<EmployeeDetails?> GetEmployeeDetails(int id);
Task<bool> EditEmployeeDetails(Employee Employee);
Task<bool> CreateNewEmployee(Employee employee);
Task<bool> DeleteEmployee(int? id);

Task<Employee?> edit_GetEmployeeDetails(int? id);



}
}
using ASPMVCNETCRUD.Models;

namespace ASPMVCNETCRUD.Repository
{
public interface IEmployeeRepository
{


Task<IEnumerable<EmployeeDetails>> GetEmployeeRecords();
Task<EmployeeDetails?> GetEmployeeDetails(int id);
Task<bool> EditEmployeeDetails(Employee Employee);
Task<bool> CreateNewEmployee(Employee employee);
Task<bool> DeleteEmployee(int? id);

Task<Employee?> edit_GetEmployeeDetails(int? id);



}
}
cap5lut
cap5lut10mo ago
yeah then my mock example would fit it and generally the use of IEmployeeRepository is easily mockable, as u do not have any complex call chains on it, unlike the EF core stuff so basically to test the repository implementation, use an in memory db provider to test the controllers, mock the repository
chino
chino10mo ago
thanks a lot man it's all clearer to me now been stuck on this for days
cap5lut
cap5lut10mo ago
glad i could help o7
chino
chino10mo ago
searching for answers thanks again!
cap5lut
cap5lut10mo ago
btw, i assume u r using Moq as mocking library right now?
chino
chino10mo ago
yes
cap5lut
cap5lut10mo ago
BleepingComputer
Popular open source project Moq criticized for quietly collecting data
Open source project Moq (pronounced "Mock") has drawn sharp criticism for quietly including a controversial dependency in its latest release. Moq's 4.20.0 release from this week included another project, SponsorLink, which caused an uproar among open source software consumers, who likened the move to a breach of trust.
cap5lut
cap5lut10mo ago
iirc NSubstitute is the new drop in for Moq now https://nsubstitute.github.io/
chino
chino10mo ago
damn guess i should switch just to be safee
cap5lut
cap5lut10mo ago
yeah, sad story =/ especially in EU this could lead to legal issues so for me its not an option to use Moq anymore as long as this stuff stays in the source. and the trust is gone that it wont reappear
chino
chino10mo ago
glad i use a dummy email when practicing stuff i have like 2389238283 emails for things like installations/game stuff
Accord
Accord10mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.