Before you start:
- We use PostgreSQL with Postgis extension (Can't use inMemoryDB option, because of Postgis' geometry that we are using)
- We do not use the repository pattern
- We use DbContext to access the DbModels and use Linq expressions on them
- We use Database First principle
This sort of question has been asked before in varying degreesLike here, where they talk about it, however we do NOT implement the repository pattern but I feel it has not been answered in a concise way and so I ask it again. References or general guide is welcomed, so thank you in advance.
This is what I have so far. Controller:
public class StartTripController : Controller
{
private readonly DbContext _dbContext;
public StartTripController(DbContext DbContext) => _DbContext = DbContext;
[Route("connect")]
[HttpGet]
public async Task<IActionResult> StartTrip(MessageDto messageDto, StartTripDto startTripDto)
{
if (ModelState.ErrorCount > 0)
return StatusCode(400);
var userToCheck = await _DbContext.User
.Select(i => new UserDto { UserId = i.Id, PhoneId = i.PhoneId, AppInfoDto = new AppInfoDto { IsAppInDebug = false } })
.SingleOrDefaultAsync(u => u.PhoneId == startTripDto.UserDto.PhoneId); //checks if User is in DB, returns Null if not
if (userToCheck == null) //user does not exist
{
//Make new User entity and save the changes to DB async
UserDto newUserToReturn = new UserDto { UserId = user.Id, AppInfoDto = new AppInfoDto { IsAppInDebug = user.DebugMode } };
return GenerateResponseWithStatus200(messageDto, newUserToReturn);
}
//user exists
return GenerateResponseWithStatus200(messageDto, userToCheck);
}
My Test looks like this:
public class StartTripControllerTest : ControllerTest<StartTripController>
{
private DbContext _mockDbContext;
protected override StartTripController GetController()
{
var mockDbContext = new Mock<DbContext>();
var userData = new List<User>
{
new User{PhoneId = "Phone1", Id = 1, ReportProviderId = 1, UserPhone = null, DebugMode = true, IpAddress = "empty", DeviceUser = null, Credential = null},
new User{PhoneId = "Phone2", Id = 2, ReportProviderId = 2, UserPhone = null, DebugMode = true, IpAddress = "empty", DeviceUser = null, Credential = null}
};
var mockData = userData.AsQueryable().BuildMock(); //BuildMock is from https://github.com/romantitov/MockQueryable
mockDbContext.Setup(x => ???what do I write here??).Returns(mockData.Object);
return new StartTripController(mockDbContext.Object);
}
[Fact]
public async System.Threading.Tasks.Task StartTrip_ReturnUser_JsonAsync()
{
// Arrange
StartTripController startTripController = GetController();
MessageDto messageDto = new MessageDto ();
StartTripDto startTripDto = new StartTripDto();
//code omitted for readiblity
var result = await startTripController.StartTrip(messageDto, startTripDto);
}
}
Things I figured out:
- You have to Mock Interfaces in order for async methods to work As per Microsoft's post
Things I am stuck on:
- How do I mock the DbContext or I guess the Model in this case, so that I can use LINQ expressions, like I do I my regular code?