Unit test command class with mock repository - c#

My application is designed using the CQRS pattern and repositories, how can I create unit tests for my command classes without connecting to the database?
We are using Moq to create mocks of our repositories.

You have to mock your Database Layer. Similarly you can Mock Repositor layer also instead of Database Layer.
[TestClass]
public class TestCommandServiceTests
{
private readonly TestService _testService;
private readonly ITestRepositor _testRepository;
private readonly Mock<IDatabaseLaye> _mock;
[SetUp]
public void Setup()
{
_mock = new Mock<IDatabaseLayer>();
_testRepository = new TestRepository(_mock);
_testService = new TestService(_testRepository);
}
[Test]
public void TestMethod_ValidRequest_ShouldTestSuccessfully()
{
// Arrange
var request = new TestMethodRequest();
this._mock.Setup(c => c.TestSPMethod(null)).Returns(1000);
// Act
var response = _testService.TestMethod(request);
// Assert
Assert.IsNotNull(response);
Assert.AreEqual(1000, response.Id);
}
}

Of course you can mock the database (and you even should, says the textbook). But this soon gets very cumbersome, especially when complex database constraints are into play.
In practice it might be more productive to have a local test database (e.g. in-memory with SQLite or MS SQL CE, if possible) and test against the entire 'persistence stack' (in your case: Commands, Repositories AND database) in one go. This is the method that is recommended in the book The Art of Unit Testing, and I found it very helpful in practice.

Related

How to prevent database effect in C# MVC Unit testing?

when I applying the unit testing on Insert, Update and Delete operation. At that time the record inserted, updated and deleted in the database as well.
How it possible?
Can anyone give the solution to prevent the database effect?
Thanks,
Ideally you should be using mocking for scenarios where db interaction is there. Make sure you have separate out your db interaction logic and it is interface driven. Then you can create mock objects, wherein you define the expectation of your db interaction interfaces. So for example, if for example InsertSomething() method is called, what should be returned from this method? and so on. Sharing some links on details about unit testing and mocking.
https://msdn.microsoft.com/en-us/library/ff650441.aspx
https://github.com/Moq/moq4
http://www.developerhandbook.com/unit-testing/writing-unit-tests-with-nunit-and-moq/
Testing a MVC Controller fails with NULL reference exception
As another option, you can go for separate real database for testing purpose, if it is essential to execute tests against database. You can also, execute sql script at the start and after running the test to seed and clean data respectively to keep the database pristine
It is possible either by mocking your database (used in unit tests) or creating new database used only for testing purpose (integration tests).
I would recommend using these two approaches together. Remember, that amount of unit tests should be much bigger than integration tests.
Here is simple example how to mock database (using Moq library).
public class HomeController : Controller
{
private IUserRepository _repository;
public HomeController(IUserRepository repository)
{
_repository = repository;
}
public ActionResult AddNewUser(User newUser)
{
_repository.AddUser(newUser);
return View();
}
}
public interface IUserRepository
{
void AddUser(User newUser);
}
public class UserRepository : IUserRepository
{
private DBContext _context;
public UserRepository(DBContext context)
{
_context = context;
}
public void AddUser(User newUser)
{
_context.Users.Add(newUser);
}
}
[Test]
public void ShouldMockRepository()
{
// Given
var repository = new Mock<IUserRepository>();
var controller = new HomeController(repository.Object);
// When
controller.AddNewUser(new User());
// Then
repository.Verify(r => r.AddUser(It.IsAny<User>()), Times.Once);
}

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.

How do I execute an automated test with the option of specifying test type

How do I execute an automated test with the option of specifying it as a unit test or "light-weight integration test" without writing the same test twice and only changing the interface it depends on to make it either of the two?
Specifically, I want to execute one test and specify it as a unit test or an integration test.
Based on the mode I select, the test should generate a service interface.
I do not want to maintain two sets of identical code with the only difference being an interface:
Service for accessing external system (integration test)
MockService (unit test)
Example:
Construct testable business layer logic
It doesn't make sense to have a morphic test.
A unit test tests that a single piece of code works in isolation.
An integration tests tests that your code works when integrated into a larger codebase.
For instance, acceptance criteria and psuedocode for unit testing a viewmodel:
public TestMeViewModelTests {
public when_adding_a_warehouse_then_should_call_service_AddNewWarehouse_given_WarehouseModel {
//Arrange
var warehouseViewModel = new WarehouseViewModel { id=1 };
var service = new Mock<IService>();
var interfaceViewModel = new TestMeViewModel(service.Object);
//Act
interfaceViewModel.AddWarehouseCommand(warehouseViewModel);
//Assert
service.Verify(s=>s.AddNewWarehouse(wareHouseViewModel), Times.Once);
}
}
See, there's no cross-pollination of concerns. You're just testing that an idempotent operation is called when adding a new warehouse. If you were using an ORM, then you'd also have unit tests verifying that the dataservice calls are occurring.
If you were going to do an integration test, then your test project would be pointed to a "WarehouseTest" connectionstring that mirrors production, and your integration test might do that same logic, but then check to make sure that the warehouse that is inserted by the test is actually in your DB at the end of the test.
Okay, I think I understand what's happening now.
You want to be able to change the implementation used of an interface at runtime in order to change the location the unit tests run against.
In that case, you want some kind of abstract factory pattern.
Example:
public class ViewModel {
IService _service;
public ViewModel(IServiceFactory factory){
_service = factory.Create();
}
public void SaveWarehouse(Warehouse aWarehouse) {
_service.AddWarehouse(aWarehouse);
}
}
public interface IServiceFactory {
IService Create();
}
public class ProductionFactory : IServiceFactory { //Dependency injected
public IService Create() {
return new ProdService();
}
}
Unit Test:
public class ViewModelTest {
public void when_adding_warehouse() {
//Arrange
var aWarehouse = new WarehouseViewModel { id=1 };
var serviceFactory = new Mock<IServiceFactory>().Object);
var service = new Mock<IService>();
serviceFactory.Setup(factory => factory.Create()).Returns(service.Object);
var viewModel = new ViewModel(serviceFactory.Object);
//Act
viewModel.AddWarehouseCommand(warehouseViewModel);
//Assert
service.Verify(s=>s.AddNewWarehouse(aWarehouse), Times.Once);
}
}
Integration Test:
Your integration test will include a local internal IService implementation and a local internal IServiceFactory implementation returning the local IService implementation. All of your tests will run perfectly fine and you can control where the data goes to very easily.
Add an entry to the app config.
App Config:
<appSettings>
<add key="IsUnitTest" value="True" />
</appSettings>
Then get the key/value pair from the config file and set your service dependency based on the config value.
Test
[TestClass]
public class MyTest
{
IServices _service = null;
[TestInitialize]
public void Setup()
{
var isUnitTest = bool.Parse(ConfigurationManager.AppSettings["IsUnitTest"]);
if (isUnitTest)
{
_service = new MockService();
}
else
{
_service = new Service();
}
}
.
.
.
I disagree C Bauer. No consensus here at all. Mocks and dependency injection go a long way to solving this problem. I've seen this approach used more frequently over the last couple of years and it works fine.
Usually in Agile environments where roles are cross functional. Some teams want a single code base/solution to work from. Especially where the size of the code base is relatively small, having "unit" tests able to function as light weight Integration tests works fine. There is no black and white solution here, only the one that works best for the problem at hand. Regardless of what others say there are multiple ways to approach this problem and the solutions/approaches are growing and changing all the time.

MS Test for Void Methods

I have a void method, which i need to unit test, can some one please help me how to do it
[TestMethod()]
public void ProcessProductFeedTest()
{
// TODO: Initialize to an appropriate value
ProductDataServiceProvider target = new ProductDataServiceProvider();
target.ProcessProductFeed();
Assert.Inconclusive("A method that does not return a value cannot be verified.");
}
in the above code ProcessProductFeed() is a void method which gets some data from SQL server DB and publish to TIBCO, how can i write a unit test case for the same
Well, you should test that the data is published to TIBCO, basically.
For any method, your tests should either test that the value returned is correct if the primary purpose is to compute something, or that the appropriate side-effects have occurred if that's the primary purpose of the method. (You then test the error conditions as well, of course.)
Without knowing anything about either TIBCO or your architecture, I can't really comment on how you go about testing the publishing part. I would personally separate out the three stages of reading, processing and publishing - then each part can be tested in isolation from the others.
Abstract persistence and TIBCO communication from your class. E.g. you can use some repository interface for communication with SQL server :
public interface IProductsRepository
{
IEnumerable<Product> GetSomeProducts();
// other members
}
And some gateway for communcation with TIBCO (I named it Stock, but you should provide business specific names):
public interface IStockGateway
{
void DoSomethingWithProducts(IEnumerable<Product> products);
// other members
}
Then make your class depend on these abstractions. You will be able to mock them and verify class behavior:
public class ProductDataServiceProvider
{
private IProductsRepository _productRepository;
private IStockGateway _stockGateway;
// inject implementations
public ProductDataServiceProvider(
IProductRepository productRepository,
IStockGateway stockGateway)
{
_productRepository = productRepository;
_stockGateway = stockGateway;
}
public void ProcessProductFeed()
{
// use repository and gateway
}
}
Now, back to test. What are responsibilities of your provider - get some products from product repository (implementation of this repository will load products from SQL database) and pass them to gateway (implementation of gateway will publish products to TIBCO). Here is test which uses Moq library:
[TestMethod]
public void ShouldPassSomeProjectToStock()
{
// Arrange
var products = new List<Product>() { }; // create some products
var mockRepository = new Mock<IProductRepository>();
mockRepository.Setup(r => r.GetSomeProducts()).Returns(products);
var mockGateway = new Mock<IStockGateway>();
mockGateway.Setup(g => g.DoSomethingWithProducts(products));
var provider = new ProductDataServiceProvider(mockRepository.Object,
ockGateway.Object);
// Act
provider.ProcessProductFeed();
// Assert
mockRepository.VerifyAll(); // verify products retrieved from repository
mockGateway.VerifyAll(); // verify products passed to gateway
}

How do i mock a Interface with Moq or NInject Mocking Kernel

I just waded through questions and blogs on the subject of mocking and Dependency Injection. Come to a conclusion i just need to mock the interface that is consumed by client. I am looking forward to testing a simple use case here with no idea.
The Contract
public Interface IApplicationService
{
bool DeleteApplication(int id);
ApplicationDto AddApplication(ApplicationDto application);
IEnumerable<ApplicationDto> GetApplications();
}
Implementation ( I am going to mock )
public Class ApplicationService:IApplicationService
{
private EntityFrameworkRepo repo;
public ApplicationService()
{
repo = new EntityFrameworkRepo();
}
public ApplicationDto Add(ApplicationDto dto)
{
//add to dbcontext and commit
}
}
Mocking Code
[Test(Description = "Test If can successfully add application")]
public void CanAddApplication()
{
//create a mock application service
var applicationService = new Mock<IApplicationService>();
//create a mock Application Service to be used by business logic
var applicationDto = new Mock<ApplicationDto>();
//How do i set this up
applicationService.Setup(x => x.GetApplications()).Returns(IEnumerable<applicationDto.Object>);
}
And i for one am sure i need to test the business logic rather than mocking it. So what is it exactly i have to do to test my ApplicationService but then keep the entity framework out.
btw to speak of ApplicationService, it uses constructor injection with NInject. So mocking this with NInject.MockingKernel will setup dependency chain?
There is little or no benefit using dependency injection (IOC) container in unit testing. Dependency injection helps you in creating loose coupled components, and loose coupled components are easier to test, thats it.
So if you want to test some service, just create mockups of it dependencies and pass them to that service as usual (no need to involve IOC container here, I hardly can imagine, that you will need some features of IOC containers - like contextual binding, interception etc. - inside unit test).
If you want your ApplicationService to be easy to test, it should look more like:
public class ApplicationService: IApplicationService
{
private readonly IEntityFrameworkRepo repo;
// dependency passed by constructor
public ApplicationService(IEntityFrameworkRepo repo)
{
this.repo = repo;
}
// save to db when DTO is eligible
public ApplicationDto Add(ApplicationDto dto)
{
// some business rule
if(dto.Id > 0 && dto.Name.Contains(string.Empty)){
//add to dbcontext and commit
}else{
throw new NotEligibleException();
}
}
}
Here the dependency is passed by constructor. In your application code you will use it together with an IOC container to make constructor injection (IOC container will be responsible for creating instances of IEntityFrameworkRepo).
But in unit test, you can just pass instance of some implementation of IEntityFrameworkRepo created on your own.
ApplicationDto
As long as ApplicationDto is some object that can by created by hand, I can directly use it in unit-test (creating instances by hand). Otherwise I will have to wrap it by interface like IApplicationDto, in order to be able to mock it up with Moq.
public class ApplicationDto{
public int Id {get; set;}
public string Name {get; set;}
}
Here is how could unit-test look like:
In unit test I will use mocked implementaion of IApplicationRepo, because I do not want to configure e.g. database connections, web services etc. and my primary intention is to test the ApplicationService not the underlying repository. Another advantage is that the test will be runnable without specific configuration for various machines. To mockup some db repository I can use e.g. List.
[Test(Description = "Test If can successfully add application")]
public void CanAddApplicationIfEligible()
{
var repo = GetRepo();
var appService = new ApplicationService(repo);
var testAppDto = new ApplicationDto() { Id = 155, Name = "My Name" };
var currentItems = repo.ApplicationDtos.Count();
appService.Add(testAppDto);
Assert.AreEqual(currentItems + 1, repo.ApplicationDtos.Count());
var justAdded = repo.ApplicationsDto.Where(x=> x.Id = 155).FirstOrDefault();
Assert.IsNotNull(justAdded);
///....
}
private static IEntityFrameworkRepo GetRepo{
// create a mock repository
var listRepo = new List<ApplicationDto>{
new ApplicationDto {Id=1, Name="MyName"}
};
var repo = new Mock<IEntityFrameworkRepo>();
// setup the methods you know you will need for testing
// returns initialzed list instead of DB queryable like in real impl.
repo.Setup(x => x.ApplicationDtos)
.Returns<IQueryable<ApplicationDto>>(x=> listRepo);
// adds an instance of ApplicationDto to list
repo.Setup(x => x.Add(It.IsAny<ApplicationDto>())
.Callback<ApplicationDto>(a=> listRepo.Add(a));
return repo.Object;
}
Note:
There have been realeased an ninject.mockingkernel extension. The approach described in example on wiki can make your unit-test code bit tidier, but the approach described there is definetly not depencdency injection (it is service locator).

Categories

Resources