I have just started playing with unit testing / mocks using Moq, and ran into a problem..
I have a Service layer named "CustomerService" which have following code:
public interface ICustomerService
{
Customer GetCustomerById(int id);
}
public class CustomerService : ICustomerService
{
private IRepository<Customer> customerRepository;
public CustomerService(IRepository<Customer> rep)
{
customerRepository = rep;
}
public Customer GetCustomerById(int id)
{
var customer = customerRepository.Get(x => x.CustomerId == id);
if (customer == null)
return null;
return customer;
}
}
My repository class is generic, and are following:
public interface IRepository<T> : IDisposable where T : class
{
T Get(Expression<Func<T, bool>> predicate);
}
public class Repository<T> : IRepository<T> where T : class
{
private ObjectContext context;
private IObjectSet<T> objectSet;
public Repository()
: this(new demonEntities())
{
}
public Repository(ObjectContext ctx)
{
context = ctx;
objectSet = context.CreateObjectSet<T>();
}
public T Get(Expression<Func<T, bool>> predicate)
{
T entity = objectSet.Where<T>(predicate).FirstOrDefault();
if (entity == null)
return null;
return objectSet.Where<T>(predicate).FirstOrDefault();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (context != null)
{
context.Dispose();
context = null;
}
}
}
}
Now is my question.. How can I make unit test to check whether my GetCustomerById returns null or not?
Already tried:
[TestMethod]
public void GetCustomerTest()
{
const int customerId = 5;
var mock = new Mock<IRepository<Customer>>();
mock.Setup(x => x.Get(z => z.CustomerId == customerId))
.Returns(new Customer());
var repository = mock.Object;
var service = new CustomerService(repository);
var result = service.GetCustomerById(customerId);
Assert.IsNotNull(result);
}
without luck...
You need to make the Repository<T>.Get
method virtual so Moq can override it and return the value you set up:
public virtual T Get(Expression<Func<T, bool>> predicate)
and in your test, change
mock.Setup(x => x.Get(z => z.CustomerId == customerId))
.Returns(new Customer());
to
mock.Setup(x => x.Get(It.IsAny<Expression<Func<Customer, bool>>>()))
.Returns(new Customer());
which says return a new Customer
for any Expression<Func<Customer, bool>>
passed in. Ideally you would test a specific expression, but per the accepted answer to this SO question, Moq cannot do this.
If you wanted to test that your service layer was not doing anything unexpected to the Customer
returned by the repository, instead of testing to see that any Customer
was returned, you could set up a mock Customer
(being sure to make the CustomerId
property virtual) and assert that the Customer
returned by the service layer had the expected properties.
[TestMethod]
public void GetCustomerTest()
{
const int customerId = 5;
var mockCustomer = new Mock<Customer>();
mockCustomer.SetupGet(x => x.CustomerId)
.Returns(customerId);
var mock = new Mock<IRepository<Customer>>();
mock.Setup(x => x.Get(It.IsAny<Expression<Func<Customer, bool>>>()))
.Returns(mockCustomer.Object);
var repository = mock.Object;
var service = new CustomerService(repository);
var result = service.GetCustomerById(customerId);
Assert.AreEqual(customerId, result.CustomerId);
}
HTH
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With