Entity Framework 6 and Unit Test - c#

I have been looking around for a solution but I couldn't find the answer (like here and here.)
public class ItemsRepository {
public ItemDto Get(int id) {
using (var db = new ItemContext()) {
return db.Items.FirstOrDefault(i => i.Id == id)
.ToDto();
}
}
}
I used to test this code by going all the way to the DB. I know this is not a good practice, since the unit test in this case tests the connection to the database as well.
Ideally, I want to build an in-memory database and seed it. How would I do that in this case? How do I fake ItemContext to use an in-memory list?
Note that I don't want to expose Context as a constructor, since the user will have to know about how the data is stored.

You cannot fake ItemContext because new keyword always creates a new instance of the object. Ideally, you should inject your context by dependency injection. Something like this:
public class ItemsRepository {
public ItemDto Get(int id) {
return _itemContextService.Items.FirstOrDefault(i => i.Id == id)
.ToDto();
}
}
In unit test _itemContextService should be injected and _itemContextService.Items should be configured with mock data. All logic which you should unit test is:
FirstOrDefault(i => i.Id == id).ToDto();
This is only what Get(int id) method does. Connection with database is beyond of scope in unit testing this method.
Anyway, if you cannot use some DI container or somehow inject ItemContext then you can mock your connection string in unit test project.

Related

real purpose of moq framework

I've been asked to write unit tests using Moq framework. I'm fairly new on how to write Moq tests in c#.
I'm going through this MSDN link
Here is what I'm doing right now as we are using dependency injection on repository
//Repository
public interface IRepo
{
IQueryable<MyModel> GetById( long userId );
}
public class Repo : BaseManager, IRepo
{
public Repo(myDbContext context)
{
dbContext = context; //dbContext is from BaseManager class
}
public IQueryable<MyModel> GetById( long userId )
{
return dbContext.MyModel.Where(x => x.IsActive && x.UserId == userId );
}
}
//Test class
public class Test
{
Mock<DbSet<MyModel>> mockSet;
Mock<myDbContext> mockContext;
Mock<IRepo> mockRepository;
[TestInitialize]
public void Setup()
{
var data = new List<MyModel>{
//3 records
}.AsQueryable();
var mockSet = new Mock<DbSet<MyModel>>();
mockSet.As<IQueryable<MyModel>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<MyModel>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<MyModel>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<MyModel>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
var mockContext = new Mock<myDbContext>();
mockContext.Setup(c => c.MyModel).Returns(mockSet.Object);
mockRepository = new Mock<IRepo>();
mockRepository.Setup(m => m.GetById(It.IsAny<long>())).Returns(data); //Here the GetById method is set to return all 3 records set in data object.
}
[TestMethod]
public void Test_Mock_For_Nothing()
{
var controller = new MyController(mockRepository.Object);
var result = controller.GetById(1); //this will call GetById method in the repository
Assert.AreEqual(result.Count(), 1);//This will fail as we will get count as 3
}
}
So, the logic in the repository is never executed though I mocked context and repository. As GetById method would directly return the result with 3 records as per dummy data.
I'm expecting the dummy data to be filtered out based on the logic in the repository method. Is this possible with Moq ?
What is the real purpose of using Moq framework when the repository code is not being executed ?
Given that you've mocked your repository, without seeing the Controller logic, I'm not sure why you would need to mock the dbContext. But effectively with this test you are testing the Controller logic and not the repository as you've mocked the repository and what is returned from the GetById in the repository.
If you wish to test the filter logic in the repository, you would need to mock the dbContext (as you have done) and in the test create a new concrete Repository instance and test the data that is returned from a call to GetById.
So you mock dbContext.MyModel, returning your three items and let the Where call perform the filtering.
There's plenty of useful information out there regarding use of a mocking framework, but everyone has slightly differing opinions about what you should test and small a unit you should test in a single unit test, experience and personal preference is the key here.
In terms of your test I would say there is very little benefit to using a mocking framework or even having this test. My thoughts are:
1) If you have a repository write an integration test as you want to prove that you are returning data from the database/web service etc
2) Use Moq or RhinoMocks in situations where you want to test some business logic/behaviour
with Unit tests you try to test/harden your Business logic. in your repositories should not be any BL (Businesslogic). with your MOCK Framework you disable think you donĀ“t want to test. -> Repository = access to Data.
With this you are able to change your way you get your data (repository) without any changes on your Businesslogic/UnitTests :)
PS: if you want to test your Repositories or even more you should aim to integration tests or even to End to End tests.

How do I unit test a method to add an item to a database?

I have an item and I am adding it to the database using this method:
public Messages addItem(Item item)
{
Messages resultMessage = Messages.Success;
using (IUnitOfWork unitOfWork = new UnitOfWork())
{
IItemRepository itemRep = new ItemRepository(unitOfWork);
try
{
itemRep.Insert(item);
unitOfWork.Commit();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
resultMessage = Messages.DB_Failure;
}
}
return resultMessage;
}
Now I have to make write a unit test for this method to check if the item is being added to the database. I have no idea how I should do that, can someone help me?
Your code is coupled with the ItemRepository and the UnitOfWork implementations. Ideally you should decouple them and use mocks to verify that the right methods are called.
A possible solution:
Make the Repository a property on your unit of work
Don't create the Unit of Work directly, use a factory for that
Make the factory a dependency of your class
In your test pass a mock of the factory to the class you are testing that returns a mock of the Unit Of Work
Return a mock of the Repository on your UoW mock
Verify that the right methods are called on your Repository mock and Unit of Work mocks
This would be an example. I have used Moq as the mocking framework. And put the test method inside the class, but you can get the idea:
class MyClass
{
private readonly IUnitOfWorkFactory _factory;
public MyClass(IUnitOfWorkFactory factory)
{
_factory = factory;
}
public Messages addItem(Item item)
{
Messages resultMessage = Messages.Success;
using (IUnitOfWork unitOfWork = _factory.GetUnitOfWork())
{
try
{
unitOfWork.ItemRep.Insert(item);
unitOfWork.Commit();
}
catch (Exception e)
{
Console.WriteLine(e.StackTrace);
resultMessage = Messages.DB_Failure;
}
}
return resultMessage;
}
public void Test()
{
// Arrange
var factoryMock = new Mock<IUnitOfWorkFactory>();
var uowMock = new Mock<IUnitOfWork>();
var repositoryMock = new Mock<IItemRepository>();
factoryMock.Setup(f => f.GetUnitOfWork()).Returns(uowMock.Object);
uowMock.Setup(u => u.ItemRep).Returns(repositoryMock.Object);
var sut = new MyClass(factoryMock.Object);
// Act
var item = new Item();
sut.addItem(item);
// Assert
repositoryMock.Verify(r => r.Insert(item), Times.Once);
uowMock.Verify(u => u.Commit(), Times.Once);
}
}
You say that the goal is to "check if this item is added to the database".
This is something you do not normally write a unit test for because it is the responsibility of the database, which presumably you are not the one developing.
A better case for a unit test is to mock out the database and check the logic that decides to add something to the database. For instance:
A Unit of Work is described by a customer/operator.
Your component queries the database for the existence of the item.
No corresponding item exists.
Your component adds the item to the database.
This is achieved by using just a mock of the database and it is testing your code, rather than the database.
As your method currently stands, it cannot be unit tested as it's hard-coded to write to the database.
The conventional way around this is to pass an instance of IItemRepository into the method, rather than having the method create it. Do that and then you are free to create a mocked IItemRepository implementation that can report what's being written to the DB.
As other answers suggested: try to separate your class under test from difficult/slow to test dependencies like the database. You can use a number of approaches to achieve this result, but they all come down to the same:
Don't create (new up) dependencies that make unit testing difficult in the code you want to test itself (like your unitofwork/repository). Rather, ask these dependencies from the outside world (google Dependency Inversion/DI for further info).
If you want to test the implementation of the repository with a real database, I suggest you test through the public API of your repository. Don't go writing "SELECT * FROM Items" queries yourself, but use a repository.GetItem(...) method if available. That way your tests are less brittle and decoupled from the actual implementation of your repository class.

Proper use of MOQ in a Unit Test

Given the following, is this the proper use of MOQ? I am very new to "mocking", "stubbing", "faking", etc. and just trying to wrap my head around it.
The way I understand it is that this mock is providing a known result, so when I test this service using it, the service reacts properly?
public interface IRepository<T> where T : class
{
void Add(T entity);
void Delete(T entity);
void Update(T entity);
IQueryable<T> Query();
}
public interface ICustomerService
{
void CreateCustomer(Customer customer);
Customer GetCustomerById(int id);
}
public class Customer
{
public int Id { get; set; }
}
public class CustomerService : ICustomerService
{
private readonly IRepository<Customer> customerRepository;
public CustomerService(IRepository<Customer> customerRepository)
{
this.customerRepository = customerRepository;
}
public Customer GetCustomerById(int id)
{
return customerRepository.Query().Single(x => x.Id == id);
}
public void CreateCustomer(Customer customer)
{
var existingCustomer = customerRepository.Query().SingleOrDefault(x => x.Id == customer.Id);
if (existingCustomer != null)
throw new InvalidOperationException("Customer with that Id already exists.");
customerRepository.Add(customer);
}
}
public class CustomerServiceTests
{
[Fact]
public void Test1()
{
//var repo = new MockCustomerRepository();
var repo = new Mock<IRepository<Customer>>();
repo.Setup(x => x.Query()).Returns(new List<Customer>() { new Customer() { Id = 1 }}.AsQueryable());
var service = new CustomerService(repo.Object);
Action a = () => service.CreateCustomer(new Customer() { Id = 1 });
a.ShouldThrow<InvalidOperationException>();
}
}
I am using xUnit, FluentAssertions and MOQ.
The way I understand it is that this mock is providing a known result,
so when I test this service using it, the service reacts properly?
This statement is correct - the unit test should be verifying that the class you're testing (in this case, CustomerService) is exhibiting the behavior you desire. It's not intended to verify that its dependencies are behaving as expected (in this case, IRepository<Customer>).
Your test is good* - you're setting up your mock for the IRepository and injecting into your SystemUnderTest, and verifying that the CustomerService.CreateCustomer() function is exhibiting the behavior that you expect.
*The overall setup of the test is fine, but I'm not familiar with xUnit, so the final two line's syntax is foreign to me, but it looks like it's correct based on the semantics. For reference, you would do the last two lines in NUnit like so:
Assert.Throws<InvalidOperationException>(() => service.CreateCustomer(...));
The test looks fine to me, the mock just provides a fake repository that returns a hardcoded answer just for the test, so the test only cares about the service you're testing and don't deals with a real-life database or whatever, since you're not testing it here.
I would only add one thing to the test to be even more complete. When you setup method calls on the mocks, make sure they were really called by the system under test. After all, the service is supposed to ask the repo for some object and throw only under a certain return value. Moq in particular provides a syntax for this:
repo.VerifyAll();
What this does is simply checking that the setups you've placed before were actually called at least once. This can protect you from errors where the service just throws the exception right away without calling the repo (easy to spot in examples like yours, but with complex code it's easy to miss a call). With that line, at the end of your test, if your service didn't called the repo asking for the list (and with that specific set of parameters), the test will fail too, even if the exception was properly thrown.

Create service layer with mocked data from LINQ DataContext

I'm using LINQ-to-SQL with ASP.NET MVC 4, and as of this moment I have a repository layer which contacts a real database. This is not very good when I want to unit test.
Also there should never be a logic in the repository layer, so this is why I want to mock the LINQ DataContext so I can create a service layer that talks either to the mock DataContext or to the real DataContext.
I see that my LINQ DataContext class inherits DataContext, but there is no interface, so I can't really mock that. I also see that DataContext uses Table<> class and there exists an interface ITable, so I probably could mock that. Also my LINQ DataContext is a partial class, so maybe I could manipulate that in some kind of way?
When I google this, all articles are from 2008 and are outdated.
Can anyone guide me in the right appropriate direction?
Here is an example of what I want to do. I will have seperate service class for each controller.
public class MyServiceClass
{
IDataContext _context;
// Constructors with dependency injection
public MyServiceClass()
{
_context = new MyRealDataContext();
}
public MyServiceClass(IDataContext ctx)
{
_context = ctx;
}
// Service functions
public IEnumerable<ModelClass> GetAll()
{
return _context.ModelClass;
}
public ModelClass GetOne(int id)
{
return _context.Where(s => s.ID == id).SingleOrDefault();
}
}
Although Linq-to-Sql is still supported in .NET 4+, it has been pushed back in favor of Entity Framework. That's probably why you're finding mostly older articles.
Anyway the best way to go is to write your own DataAccess layer-interface, used through your application. You then can have an implementation of that interface that uses your linq-to-sql for production and a mocked implementation for your unit tests.
Use dependency injection to instantiate the actual implementation class.
For creating a mock implementation you do it either manually (Creating a class in your test project that implements the IDataContext interface but returns hard-coded data) or use one of the mocking frameworks around there.
I have not used every one of them but moq was quite nice. Microsoft has now also their framework in Visual Studio 2012 called Fakes, worth looking at.
Example of using moq
var expectedResultList = new List<ModelClass>(){ ... };
var mockDataContext = new Mock<IDataContext>();
mock.Setup(c => c.GetAll()).Returns(expectedResultList);
MyServiceClass service = new MyServiceClass(mockDataContext.Object);
var list = service.GetAll();
Assert.AreEqual(expectedResultList, list);
In this code you set up your mock object so that it will return your expected list when the GetAll method is called.
This way you can easily test your business logic based on different returns from your data access.
Example of IDataContext
public interface IDataContext<T>
{
IEnumerable<T> GetAll();
T GetById(int id);
int Save(T model);
}
public class LinqToSqlDataContext<T> : IDataContext<T>
{
private DataContext context = new DataContext();
public IEnumerable<T> GetAll()
{
// query datacontext and return enumerable
}
public T GetById(int id)
{
// query datacontext and return object
}
public int Save(T model)
{
// save object in datacontext
}
}
public class MyFirstServiceClass
{
private IDataContext<MyClass> context;
public MyFirstServiceClass(IDataContext<MyClass> ctx)
{
this.context = ctx;
}
....
}
public class MySecondServiceClass
{
private IDataContext<MySecondClass> context;
public MyFirstServiceClass(IDataContext<MySecondClass> ctx)
{
this.context = ctx;
}
....
}

How to test EF Models

I am trying to figure out how to write Entity Framework Code First code via TDD. I am finding it hard since it I do not have a test database as I have had in the past with Ruby On Rails. Probably easier to explain with an example:
Currently I have:
public interface IMyContext
{
IDbSet<UserProfile> Users { get; set; }
}
and
public class UserModel
{
IMyContext myContext;
UserModel(IMyContext myContext)
{
this.myContext = myContext;
}
UserProfile GetUser(int id)
{
return myContext.Users.Where(u => u.id == id);
}
}
I am not sure how to test the UserModel code without a running database. I am aware that I can mock the MyContext - but the code myContext.Users.Where ... may involve complex mocking? Have I structured the code wrong? How can I write tests for models without having a test database? Or should I fake the context?
Thanks!
Break your code down into core components and you will realize that all you need to do is mock the context's Users property. After that, the Where is really just a static method working against an IEnumerable object
var users = myContext.Users;
var returnEnumerable = Enumerable.Where(users, u=>u.id == id);
return returnEnumerable
So, just mock your context in such a way that when .Users is called, it returns an IDbSet<UserProfile> of your making

Categories

Resources