Reputation: 243
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?
Upvotes: 6
Views: 14599
Reputation: 4583
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:
This is achieved by using just a mock of the database and it is testing your code, rather than the database.
Upvotes: 1
Reputation: 3705
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:
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);
}
}
Upvotes: 7
Reputation: 750
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.
Upvotes: 0
Reputation: 43264
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.
Upvotes: 0