I'm currently trying to moq my Cafe Get method which will throw a ArgumentNullexception if the cafe ID is not found.
Error
System.NotSupportedException : Unsupported expression: x => x.Cafe
Non-overridable members (here: Context.get_Cafe) may not be used in setup / verification expressions.
Is this occurring because moq is unable to handle one of the setup expressions?
Unit test
[Fact]
public async Task GetCafeByIdAsync_Should_Throw_ArgumentNullException()
{
var cafe = new List<Cafe>()
{
new Cafe { Name = "Hanna", CafeId = 1},
new Cafe { Name = "Bella", CafeId = 2 }
}.AsQueryable();
var mockSet = new Mock<DbSet<Cafe>>();
mockSet.As<IQueryable<Cafe>>().Setup(m => m.Provider).Returns(cafe.Provider);
mockSet.As<IQueryable<Cafe>>().Setup(m => m.Expression).Returns(cafe.Expression);
mockSet.As<IQueryable<Cafe>>().Setup(m => m.ElementType).Returns(cafe.ElementType);
mockSet.As<IQueryable<Cafe>>().Setup(m => m.GetEnumerator()).Returns(cafe.GetEnumerator());
var mapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new AutoMapperProfile());
}).CreateMapper();
var contextMock = new Mock<Context>();
contextMock.Setup(x => x.Cafe).Returns(mockSet.Object); //failing here
var cafeService = new CafeService(contextMock.Object, mapper);
await Assert.ThrowsAsync<ArgumentNullException>(() => cafeService.Get(2));
}
SUT
public async Task<VersionResponse> Get(int cafeId)
{
var cafe = await _context.Cafe.Where(w => w.CafeId == cafeId).ToResponse().FirstOrDefaultAsync();
return new VersionResponse()
{
Data = cafe
};
}
Moq relies on being able to create a proxy class that overrides properties. The Context.Cafe can't be overridden. Try declaring that property virtual.
public virtual IDbSet<Cafe> Cafe { get; set; }
Try setup mock on Set method instead
public virtual DbSet<TEntity> Set<TEntity>() where TEntity : class;
in your case
var contextMock = new Mock<Context>();
contextMock.Setup(x => x.Set<Cafe>()).Returns(mockSet.Object);
I Got a Better way For Integration Tests
You can Use Transaction RollBack for this Type of Tests
in this way you can do what ever you want in Db and then every single movement in Db are back to last state of Before Running Tests
if you using Ef you can add this class to your Test Project and Enjoy it
public abstract class PersistTest<T> : IDisposable where T : DbContext, new()
{
protected T DBContext;
private TransactionScope scope;
protected PersistTest()
{
scope = new TransactionScope();
DBContext = new T();
}
public void Dispose()
{
scope.Dispose();
DBContext.Dispose();
}
}
this class help you to write better integration tests,
your test class should inherited from this abstract class and pass your context class as a instance of DbContext
and one more thing about your Codd you should seperate your Logic and DataAccess from each other
just define a interface Called ICofeeRepository and take your methods in it
Your Code Break the Single Responsibility principle
Your Service Should be Like
public class CoffeService
{
//inject cafe repository ; _repo
public async Task<VersionResponse> Get(int cafeid)
{
var cafe = _repo.FindById(cafeid);
if (cafe == null)
throw Exception("");
//other wise .....
}
}
and your Repository Should be Like
public interface ICafeRepository
{
Cafe Get(int cafeid);
}
Related
I'd like to test my logic which expects three different interfaces. How can I unite these, because I can't use mock methods while I have three instances. I guess I did something very wrong with the repositories but I have no idea. Thank you for your help!
[Test]
public void TestThatLogicABCWorks()
{
Mock<IRepositoryA> mockInstance1 = new Mock<IRepositoryA>();
Mock<IRepositoryB> mockInstance2 = new Mock<IRepositoryB>();
Mock<IRepositoryC> mockInstance3 = new Mock<IRepositoryC>();
LogicABC logic = new LogicABC(mockInstance1.Object, mockInstance2.Object, mockInstance3.Object);
}
Edit: i have three entity classes, 1 general repository and three entity specific repos. In logic I make queries including all three entities, which I reach as:
public class LogicABC : ILogic
{
IRepository<A> ARepo; //generic repo
IRepository<B> BRepo;
IRepository<C> CRepo;
public LogicABC(IARepository ARepo, IBRepository BRepo, ICRepository CRepo)
{
this.ARepo = ARepo; //entity specific repos
this.BRepo = BRepo;
this.CRepo = CRepo;
}
public LogicABC()
{
var Entity = new ABCEntities(); //context
this.ARepo = new ARepository(Entity);
this.BRepo = new BRepository(Entity);
this.CRepo = new CRepository(Entity);
}
//queries
public List<int> Query1()
{
var q1 = from x in CRepo.GetAll()
select x.Id;
return q1.ToList();
}
I need to test these queries with mock. For example setup that logicABC.Query1() returns 1 and then verify it.
When testing a subject under test that has dependencies, the dependencies explicitly needed for the test to flow to complete should be provided.
In this case Query1() is only using ICRepository and has not shown any interaction with the other two dependencies. If that is truly the case then those other dependencies are not needed.
Based on the method under test the following assumptions are being made
public interface ICRepository : IRepository<C> {
//...
}
and something similar for the other repositories IARepository and IBRepository.
public interface IRemository<TEntity> {
IEnumerable<TEntity> GetAll();
//...other members
}
public class C {
public int Id { get; set; }
//...other members
}
So the test for Query1 could be done as follows.
[Test]
public void LogicABC_Query1_Should_Return_One_Id() {
//Arrange
int expected = 123456789;
var items = new [] { new C { Id = expectedId } }
Mock<IRepositoryC> mock = new Mock<IRepositoryC>();
mock.Setup(_ => _.GetAll()).Returns(items);
LogicABC logic = new LogicABC(null, null, mock.Object);
//Act
List<int> list = logic.Query1();
//Assert
mock.Verify(_ => _.GetAll(), Times.Once());
//checking expected behavior - using FluentAssertions
list.Should().HaveCount(1);
int actual = list.First();
actual.Should().Be(expected); // using FluentAssertions
}
The unit test above tests the expected behavior of one subject method. The same pattern can be done for other members of the class under test.
You need to mock methods in every repository mock, i.e. in mockInstance1, mockInstance2 and mockInstance3. After this you'll be able to verify behavior inside LogicABC by checking applied mocks for every repos
UPDATE:
Your test should look like this:
[Test]
public void TestThatLogicABCWorks()
{
Mock<IRepositoryA> mockInstance1 = new Mock<IRepositoryA>();
mockInstance1.Setup(foo => foo.Do()).Returns(() => 1);
Mock<IRepositoryB> mockInstance2 = new Mock<IRepositoryB>();
mockInstance2.Setup(boo => boo.Do2()).Returns(() => 2);
Mock<IRepositoryC> mockInstance3 = new Mock<IRepositoryC>();
mockInstance3.Setup(doo => doo.Do3()).Returns(() => 3);
LogicABC logic = new LogicABC(mockInstance1.Object, mockInstance2.Object, mockInstance3.Object);
logic.DoLogic();
// do some asserts here
}
I have an IUnitOfWork interface that encapsulates my custom repositories. My custom repositories in turn inherit from an IRepository interface.
// The class that I am attempting to unit test
// EmployeeBusiness.cs
private readonly IUnitOfWork _unitOfWork;
public EmployeeBusiness(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public EmployeeDto AddEmployee(EmployeeDto employeeDto)
{
var employee = Mapper.Map<Employee>(employeeDto);
if (employee == null) return null;
_unitOfWork.Employees
.Add(employee);
_unitOfWork.Complete();
return Mapper.Map<EmployeeDto>(employee);
}
// IUnitOfWork interface
public interface IUnitOfWork : IDisposable
{
IEmployeeRepository Employees { get; }
void Complete();
}
// IEmployeeRepository interface
public interface IEmployeeRepository : IRepository<Employee> { }
// IRepository<T> interface
public interface IRepository<TEntity> where TEntity : class
{
void Add(TEntity entity);
// I have added other methods for simplicity
}
I am struggling with unit testing the AddEmployee() method because I am getting this error:
Expected invocation on the mock once, but was 0 times: uow => uow.Employees.Add(Employee)
Configured setups:
IUnitOfWork uow => uow.Employees.Add(Employee)
Performed invocations:
IRepository`1.Add(Employee)
This is my unit test
[SetUp]
public void SetUp()
{
_employeeDto = new EmployeeDto
{
FirstName = "John",
LastName = "Smith",
BirthDate = new DateTime(1965, 12, 31)
};
_employee = new Employee
{
FirstName = "John",
LastName = "Smith",
BirthDate = new DateTime(1965, 12, 31)
};
_unitOfWork = new Mock<IUnitOfWork>();
Mapper.Initialize(cfg =>
{
cfg.AddProfile<EmployeeProfile>();
});
}
[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
_unitOfWork.Setup(uow => uow.Employees.Add(_employee));
_employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);
_employeeBusiness.AddEmployee(_employeeDto);
_unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once);
_unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}
The reason the test you provided in your answer (copied below) passes when your original fails is because your original was expecting the mock to be called with the specific reference variable you're using (in this case _employee). Perhaps you were expecting Moq and .Verify() to check for equality using .equals() instead of ==?
In the context of your method under test, this is correct and desirable - based on the name of the test you're just looking to test that the method does in fact map your input to an Employee and calls the repository's add method. If you want to make sure that data wasn't lost in the mapping, you could use It.Is(), which takes a function you can use to assert qualities of the input (such as the name matching your expected value).
If you're aiming just to test that the mapping succeeded, you may be interested in Automapper Configuration Validation as a separate test.
[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
_unitOfWork.Setup(uow => uow.Employees.Add(_employee));
_employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);
var result = _employeeBusiness.AddEmployee(_employeeDto);
//_unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once); <-- This did not work
_unitOfWork.Verify(uow => uow.Employees.Add(It.IsAny<Employee>()), Times.Once); // <-- After changing this to It.IsAny<Employee>() it worked
_unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}
I have managed to get it to work by changing my unit test
[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
_unitOfWork.Setup(uow => uow.Employees.Add(_employee));
_employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);
var result = _employeeBusiness.AddEmployee(_employeeDto);
//_unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once); <-- This did not work
_unitOfWork.Verify(uow => uow.Employees.Add(It.IsAny<Employee>()), Times.Once); // <-- After changing this to It.IsAny<Employee>() it worked
_unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}
Can anyone please help me understand the difference of using It.IsAny<Employee>() as opposed to the _employee variable?
UPDATE
The explanation can be found at Thorin's answer.
You aren't checking the return value of AddEmployee.
[Test]
public void AddEmployee_WhenCalled_AddEmployeeToDatabase()
{
_unitOfWork.Setup(uow => uow.Employees.Add(_employee));
_employeeBusiness = new EmployeeBusiness(_unitOfWork.Object);
var result = _employeeBusiness.AddEmployee(_employeeDto);
Assert.IsNotNull(result); // <---
_unitOfWork.Verify(uow => uow.Employees.Add(_employee), Times.Once);
_unitOfWork.Verify(uow => uow.Complete(), Times.Once);
}
In my unit test I want to test my method that I created for filtering data from MongoDB.
When I try to mock my function like this:
_repo.GetFluent<Location>((Arg.Any<Expression<Func<Location, bool>>>()))
.Returns(x => locations.Where(x.Arg<Expression<Func<Location, bool>>>()).ToList());
It underlines the Returns saying:
Cannot convert lambda expression.
Before when I worked on my simple project using the 2.0.0 MongoDB driver I had no problem mocking my Get() function like this, but now with the new 2.2.3 driver I have an error mocking this. Is there another way?
I've seen that the new driver is using IFindFluent and the older one I used the MongoCursor to get my data.
Should I mock the IFindFluent somehow?
This is my code for the GetFluent() method
public IFindFluent<TEntity, TEntity> GetFluent<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null) where TEntity : class, new()
{
var collection = GetCollection<TEntity>();
if (filter == null)
{
var emptyFilter = Builders<TEntity>.Filter.Empty;
return collection.Find(emptyFilter);
}
else
{
var filterDefinition = Builders<TEntity>.Filter.Where(filter);
return collection.Find(filterDefinition);
}
}
Yes, you need to mock IFindFluent. Let me show you an example.
I used NUnit and Moq for tests, driver version is 2.2.3.
public interface IRepository
{
IFindFluent<TEntity, TEntity> GetFluent<TEntity>(Expression<Func<TEntity, bool>> filter = null)
where TEntity : class, new();
}
public class LocationService
{
public long CountLocations(IRepository repository)
{
return repository.GetFluent<Location>(location => true).Count();
}
}
[TestFixture]
public class LocationServiceTests
{
[Test]
public void CountLocationsTest()
{
const long LocationCount = 5;
var locationsMock = new Mock<IFindFluent<Location, Location>>();
locationsMock.Setup(x => x.Count(default(CancellationToken))).Returns(LocationCount);
var repoMock = new Mock<IRepository>();
repoMock.Setup(repo => repo.GetFluent(It.IsAny<Expression<Func<Location, bool>>>()))
.Returns(locationsMock.Object);
var locationService = new LocationService();
long result = locationService.CountLocations(repoMock.Object);
Assert.AreEqual(LocationCount, result);
}
}
Good answer from Usein Mambediev. There is an similar example, how to mock IFindFluent with Typemock Isolator without wrapping it into the interface:
[TestMethod, Isolated]
public void TestGet()
{
var target = new ClassUnderTest();
var returnMock = Isolate.Fake.Instance<IFindFluent<Location, Location>>();
int size = 3;
Isolate.WhenCalled(() => returnMock.Count()).WillReturn(size);
Isolate.WhenCalled(() => target.GetFluent(default(Expression<Func<Location, bool>>))).WillReturn(returnMock);
Assert.AreEqual(size, target.GetFluent<Location>(location => true).Count());
}
I've put your method into the public class just in order to test. You only need to change the target.
Good luck!
I have the following classes (where PilsnerContext is a DbContext class):
public abstract class ServiceBase<T> : IService<T> where T: class, IEntity
{
protected readonly PilsnerContext Context;
protected ServiceBase(PilsnerContext context)
{
Context = context;
}
public virtual T Add(T entity)
{
var newEntity = Context.Set<T>().Add(entity);
Context.SaveChanges();
return newEntity;
}
}
public class ProspectsService : ServiceBase<Prospect>
{
public ProspectsService(PilsnerContext context) : base(context){}
}
And i'm trying to make a unit test of the Add method mocking the context like:
[TestClass]
public class ProspectTest
{
[TestMethod]
public void AddProspect()
{
var mockProspect = new Mock<DbSet<Prospect>>();
var mockContext = new Mock<PilsnerContext>();
mockContext.Setup(m => m.Prospects).Returns(mockProspect.Object);
var prospectService = new ProspectsService(mockContext.Object);
var newProspect = new Prospect()
{
CreatedOn = DateTimeOffset.Now,
Browser = "IE",
Number = "1234567890",
Visits = 0,
LastVisitedOn = DateTimeOffset.Now
};
prospectService.Add(newProspect);
mockProspect.Verify(m=>m.Add(It.IsAny<Prospect>()), Times.Once);
mockContext.Verify(m=>m.SaveChanges(), Times.Once);
}
}
But the assert:
mockProspect.Verify(m=>m.Add(It.IsAny<Prospect>()), Times.Once);
Is failing, I assume is because I'm using Context.set().Add() instead of Context.Prospects.Add() in the Add method but how is the correct way to pass this test?
The exception is:
Expected invocation on the mock once, but was 0 times: m => m.Add(It.IsAny<Prospect>()) No setups configured. No invocations performed.
Thanks in advance.
It looks like you're just missing the setup to return your DbSet:
mockContext.Setup(m => m.Set<Prospect>()).Returns(mockProspect.Object);
I tried your solution Patrick Quirk but I was getting an error telling me that DbContext.Set is not virtual.
I found the solution for that here:
How to mock Entity Framework 6 Async methods?
Creating an interface of the DbContext like
public interface IPilsnerContext
{
DbSet<T> Set<T>() where T : class;
}
That way I could mock it.
Thanks!
This is my first question btw, I'm not sure if I can mark this question as duplicated or something.
I have a custom membership provider which connects to a user repository like this:
public class MyMembershipProvider : MembershipProvider {
[Inject]
public IUserRepository UserRepository { get; set; }
...
//Required membership methods
}
I am using ninject for my DI. Now I would like to test the provider, and have a mock user repository injected to allow me to do this. So something like:
...
IList<User> users = new List<User> {
new User { Email="matt#test.com",
UserName="matt#test.com",
Password="test"
}
};
var mock = new Mock<IUserRepository>();
mock.Setup(mr => mr.FindByUsername(
It.IsAny<string>())).Returns((string s) => users.Where(
x => x.UserName.Equals(s,StringComparison.OrdinalIgnoreCase)).Single());
...
And here is where I am not certain how to proceed, how do I get my mocked repository injected into my provider so that when a unit test that makes calls to the provider uses this mock repository?
Am I asking the right questions here?
EDIT - My final solution
For what it is worth I moved away from using mock to using an InMemory repository to maintain state so the provider would properly test certain functions. Right now I am only using this to test things like my provider. I ended up with:
generic InMemoryRepository:
class InMemoryRepository<TEntity> : IRepository<TEntity> where TEntity : class {
private int _incrementer = 0;
public Dictionary<int, TEntity> List = new Dictionary<int, TEntity>();
public string IDPropertyName {get; set;}
public void Create(TEntity entity) {
_incrementer++;
entity.GetType().GetProperties().First(p => p.Name == IDPropertyName).SetValue(entity, _incrementer, null);
List.Add(_incrementer,entity);
}
public TEntity GetById(int id) {
return List[id];
}
public void Delete(TEntity entity) {
var key = (int)entity.GetType().GetProperties().First(p => p.Name == IDPropertyName).GetValue(entity, null);
List.Remove(key);
}
public void Update(TEntity entity) {
var key = (int)entity.GetType().GetProperties().First(p => p.Name == IDPropertyName).GetValue(entity, null);
List[key] = entity;
}
}
Then my actual user repository - I do not have generic ID fields which is why I am using the IDPropertyName variable:
class InMemoryUserRepository : InMemoryRepository<User>, IUserRepository {
public InMemoryUserRepository() {
this.IDPropertyName = "UserID";
}
public IQueryable<User> Users {
get { return List.Select(x => x.Value).AsQueryable(); }
}
public User FindByUsername(string username) {
int key = List.SingleOrDefault(x=>x.Value.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)).Key;
return List[key];
}
}
My membership test base class:
[TestClass]
public class MyMembershipProviderTestsBaseClass : IntegrationTestsBase {
protected MyMembershipProvider _provider;
protected NameValueCollection _config;
protected MembershipCreateStatus _status = new MembershipCreateStatus();
[TestInitialize]
public override void Initialize() {
base.Initialize();
// setup the membership provider
_provider = new MyMembershipProvider();
MembershipSection section = (MembershipSection) ConfigurationManager.GetSection("system.web/membership");
NameValueCollection collection = section.Providers["MyMembershipProvider"].Parameters;
_provider.Initialize(null, collection);
_status = new MembershipCreateStatus();
}
[TestCleanup]
public override void TestCleanup() {
base.TestCleanup();
}
}
Then my test:
[TestMethod]
public void Membership_CreateUser() {
_provider.UserRepository = new InMemoryUserRepository();
_provider.CreateUser(_email, out _status);
Assert.AreEqual(MembershipCreateStatus.Success, _status);
}
This answer provided inspiration: https://stackoverflow.com/a/13073558/1803682
Since you've exposed your repository as a property, just create an instance of your provider in your test class and set that property to your mock like so:
public void Test()
{
MyMembershipProvider provider = new MyMembershipProvder();
provider.UserRepository = mock.Object;
// Do test stuff here
// Verify mock conditions
}
Presumably your repository implementation is using the UserRepository property so when you test it, this code will use the mocked dependency.
You can setup a test module for Ninject and create the Ninject Kernel using the test module within the unit test project.
This is what an inversion of control container is for. You have one set of bindings configured for running as a website, another set for running in test, another set for running using a different backend (or whatever).
I do this so that the production and test code get initialized in the same fashion (via Ninject) and all that changes is the configuration of Ninject.
Or do what #chris house suggested. That will work too.