Reputation: 1
I want to unit test GetFooInfo method of a Foo service class that returns FooDto object and takes input FooInput object using Xunit/Moq/AutoFixture. I'm using C#, EF core with DB First approach.
public class FooService : IFooService
{
private readonly DbContext _dbcontext;
public FooService(DbContext dbcontext)
{
_dbcontext = dbcontext;
}
public async Task<FooDto> GetFooInfo(FooInput ip)
{
return await _dbcontext.Foo.Where(e => e.FooId == ip.FooId)
.Select(s=> new FooDto
{
FooId = s.FooId,
EmpId = _dbcontext.Employee.Where(e => e.EmpId == ip.EmpId).Select(s => s.EmpId).FirstOrDefault(),
EmployeeDetail = new EmployeeDetail
{
EmpAdress = ip.EmpAddress,
Age = ip.Age
},
ProductDetail = new ProductDetail
{
ProductId = ip.ProductId,
Description = ip.Description
}
}).SingleOrDefault();
}
}
Entities:
public class FooDto
{
public long FooId {get;set;}
public long EmpId { get; set;}
public EmployeeDetail EmployeeDetail {get;set;}
public ProductDetail ProductDetail {get;set;}
}
public class FooInput
{
public long FooId {get;set;}
public long EmpId { get; set; }
public string EmpAddress { get; set; }
public int Age {get;set;}
public long ProductId {get;set;}
public string Description { get; set; }
}
public class EmployeeDetail
{
public string EmpAddress { get; set; }
public int Age {get;set;}
}
public class ProductDetail
{
public long ProductId {get;set;}
public string Description { get; set; }
}
public class Employee
{
public long EmpId { get; set; }
public date DOB { get; set; }
public float Salary { get; set; }
}
public class Foo
{
public long FooId {get;set;}
public string FooType {get;set;}
}
So far I have tried following ,I got stuck in the arrange phase how to arrange data and assign it to class properties and also it involves linq queries with complex objects. , I googled but couldn't find any examples which with requrn class with linq queries. Any help would be highly appreciated
public class FooServiceTest
{
private readonly Mock<DbContext> _context;
private readonly Fixture _fixture;
public FooServiceTest()
{
_context = new Mock<DbContext>();
_fixture = new Fixture();
}
[Fact]
public async Task Foo_Test()
{
//Arrange
var fooDto = _fixture.Create<FooDto>();
var fooInput = _fixture.Create<FooInput>();
var fooService = new FooService(_context.Object);
//Act
await fooService.GetFooInfo(FooInput);
//Assert
}
}
Upvotes: 0
Views: 286
Reputation: 1284
If you're using AutoFixture there's this library called EntityFrameworkCore.AutoFixture. It uses In-Memory and SQLite providers to run setup test databases for you. It also has enough extensibility points that could allow you to use your own provider. Checkout the readme for examples.
Upvotes: 0
Reputation: 361
This is how your test can look like:
public class FooServiceTest
{
[Fact]
public void Foo_Test()
{
var expectedFoo = new Foo
{
FooId = 123
};
var expectedEmployee = new Employee
{
EmpId = 321
};
var fooInput = new FooInput
{
FooId = expectedFoo.FooId,
EmpId = expectedEmployee.EmpId
};
var mockFooSet = MockDbSet(new[] { expectedFoo }.AsQueryable());
var mockEmployeeSet = MockDbSet(new[] { expectedEmployee }.AsQueryable());
var mockContext = new Mock<DbContext>();
mockContext.Setup(c => c.Foo) // property Foo must be virtual
.Returns(mockFooSet.Object);
mockContext.Setup(c => c.Employee) // property Employee must be virtual
.Returns(mockEmployeeSet.Object);
var service = new FooService(mockContext.Object);
var actualFooDto = new service.GetFooInfo(fooInput);
Assert.Equal(expectedFoo.Id, actualFooDto.FooId);
Assert.Equal(expectedEmployee.Id, actualFooDto.EmpId);
...
}
private Mock<DbSet<TEntity>> MockDbSet<TEntity>(IQueryable<TEntity> data)
where TEntity : class
{
var mockSet = new Mock<DbSet<TEntity>>();
mockSet.As<IQueryable<TEntity>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<TEntity>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<TEntity>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<TEntity>>().Setup(m => m.GetEnumerator()).Returns(() => data.GetEnumerator());
return mockSet;
}
}
The test contains two steps:
Upvotes: 0