I got a simple application that calls a MongoDB collection, and it does various things with it.
I want to unit test my service layer using NUnit, Nsubstitute, but I have no idea how to mock a data collection that my service layer consumes.
Here is my current setup:
AutoDB:
public class AutoDb : IAutoDb
{
private readonly IMongoCollection<Auto> _AutosCollection;
public AutoDb(IConfiguration config)
{
var client = new MongoClient(config.GetConnectionString("DatabaseConnection"));
var database = client.GetDatabase("AutoDb");
_AutosCollection = database.GetCollection<Auto>("Autos");
var AutoKey = Builders<Auto>.IndexKeys;
var indexModel = new CreateIndexModel<Auto>(AutoKey.Ascending(x => x.Email), new CreateIndexOptions {Unique = true});
_AutosCollection.Indexes.CreateOne(indexModel);
}
public async Task<List<Auto>> GetAll()
{
return await _AutosCollection.Find(_ => true).ToListAsync();
}
public async Task<Auto> Get(Guid id)
{
return await _AutosCollection.Find<Auto>(o => o.Id == id).FirstOrDefaultAsync();
}
public async Task<Auto> Create(Auto Auto)
{
await _AutosCollection.InsertOneAsync(Auto);
return Auto;
}
public async Task Update(Guid id, Auto model)
{
await _AutosCollection.ReplaceOneAsync(o => o.Id == id, model);
}
public async Task Remove(Auto model)
{
await _AutosCollection.DeleteOneAsync(o => o.Id == model.Id);
}
public async Task Remove(Guid id)
{
await _AutosCollection.DeleteOneAsync(o => o.Id == id);
}
public IMongoQueryable<Auto> GetQueryable() => _AutosCollection.AsQueryable();
}
public interface IAutoDb
{
Task<List<Auto>> GetAll();
Task<Auto> Get(Guid id);
Task<Auto> Create(Auto Auto);
Task Update(Guid id, Auto model);
Task Remove(Auto model);
Task Remove(Guid id);
IMongoQueryable<Auto> GetQueryable();
}
My Service Layer
public class AutoService : IAutoService
{
private readonly IAutoDb _AutoDb;
public AutoService(IAutoDb AutoDb)
{
_AutoDb = AutoDb;
}
public async Task<Auto> CreateProfile(AutoModel model)
{
var Auto = new Auto
{
Id = new Guid(),
Type = model.Type,
Name = model.Name,
};
try
{
await _AutoDb.Create(Auto);
}
catch (MongoWriteException mwx)
{
Debug.WriteLine(mwx.Message);
return null;
}
return Auto;
}
public async Task<Auto> GetAutoById(Guid id)
{
var retVal = await _AutoDb.Get(id);
return retVal;
}
public Task<Auto> EditAuto(AutoModel model)
{
throw new NotImplementedException();
}
}
public interface IAutoService
{
Task<Auto> CreateProfile(AutoModel model);
Task<Auto> EditAuto(AutoModel model);
Task<Auto> GetAutoById(Guid id);
}
My attempt at unit testing the service layer:
public class AutoServiceTests
{
private IAutoDb _AutoDb;
[SetUp]
public void Setup()
{
_AutoDb = Substitute.For<IAutoDb>();
// I don't know how to mock a dataset that contains
// three auto entities that can be used in all tests
}
[Test]
public async Task CreateAuto()
{
var service = new AutoService(_AutoDb);
var retVal = await service.CreateProfile(new AutoModel
{
Id = new Guid(),
Type = "Porsche",
Name = "911 Turbo",
});
Assert.IsTrue(retVal is Auto);
}
[Test]
public async Task Get3Autos() {
var service = new AutoService(_AutoDb);
// Stopped as I don't have data in the mock db
}
[Test]
public async Task Delete1AutoById() {
var service = new AutoService(_AutoDb);
// Stopped as I don't have data in the mock db
}
}
How can I create a mockdb collection that can be consumed by all the tests in the class?