How to unit test with Moq location/process - c#

So I am pretty new to testing, I never really done much, so my I may lack some fundamentals.
Question 1:
I am using ASP MVC4 and want to use Moq with my unit test case. After reading there are a lot of example, I see that I am suppose to have an interface. Where exactly should this go? In the controller folder, the test project?
Question 2
If I am testing a method in my controller and it has multiple calls to the db how would I Moq that
public ActionResult Index()
{
var model = new myModel();
var pList = new List<myModel.pType>();
var sList = new List<myModel.sType>();
var results = Class1.FetchPData(); // how would I mock this
var result1 = Class1.FetchSData(); // how would I mock this
for (int i = 0; i < results.Count(); i++)
{
... do stuff
}
for (int j = 0; j < result1.Count(); j++)
{
..do stuff
}
return View("Index", model);
}
Will I have to create another method where it contains the same logic, but I will have to pass in "Mock Object" as a param to the method, and have that as an implementable method in my interface? Or re-implement my method?

After reading there are a lot of example, I see that I am suppose to
have an interface. Where exactly should this go? In the controller
folder, the test project?
There is no rule where to keep interfaces, but usually you keep them closely to code which uses them. Usually I have domain classes and services in separate assembly with repository interfaces defined there. Then I reference this assembly by Data Access assembly which have implementations of repository interfaces. And last step - I reference both assemblies from web application.
If I am testing a method in my controller and it has multiple calls to
the db how would I Moq that
Remember, good unit tests should be Fast, Isolated, Repeatable, Self-Verifying, and Timely (FIRST). Having database calls in controller does not allow you to run tests fast (database calls are very slow comparing to in-memory code), to test controller in isolation and make tests always repeatable. Also your controller simply does to many things (i.e. violates SRP principle) - it gets user input, makes database queries and prepares model for view.
So, in order to separate responsibilities and make your controller testable, you should
extract data-access related code to separate class (usually such classes called repositories). And create abstraction which will specify API between controller and repository:
public interface IYourRepository
{
IEnumerable<pType> FetchPData();
IEnumerable<sType> FetchSData();
}
Then make your controller depend on this abstraction (inverse dependency), and inject repository to controller (you can use Ninject, Unity or other dependency injection framework):
IYourRepository _repository;
public YourController(IYourRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
var model = new myModel();
foreach (var p in _repository.FetchPData())
// do stuff
foreach (var s in _repository.FetchSData())
// do stuff
return View("Index", model);
}
That will allow you to mock repository easily and provide mocked object to controller:
var repositoryMock = new Mock<IYourRepository>();
repositoryMock.Setup(r => r.FetchPData()).Returns(pList);
repositoryMock.Setup(r => r.FetchSData()).Returns(sList);
var controller = new YourController(repositoryMock.Object);
var result = controller.Index();
// Assertions

Related

Using Moq, is it possible to setup mocked tables by type?

I have the following code where I'm trying to setup the mocked table based on the data type passed to the MockDbSet method.
private Mock<DbContext> mockContext = new Mock<DbContext>();
public DbContext GetContext()
{
return mockContext.Object;
}
public void MockDbSet<T>(params T[] sourceList) where T : class
{
var queryable = sourceList.AsQueryable();
var dbSet = new Mock<DbSet<T>>();
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
mockContext.Setup(c => c.Set(typeof(T))).Returns(dbSet.Object);
}
I get the following error at the mockContext.Setup line (22):
System.NotSupportedException: Conversion between generic and non-generic DbSet objects is not supported for test doubles.
I've tried
mockContext.Setup(c => c.Set<T>()).Returns(dbSet.Object);
This does not throw the exception, but also does not setup any data.
Is it possible to setup tables this way?
Thanks
To outline mocking at the Repository level:
Given Service / Controller code that interacts with a Repostory through a contract interface:
public interface IOrderRepository
{
IQueryable<Order> GetOrderById (int orderId);
IQueryable<Order> GetOrdersForCustomer (int customerId);
}
This is the preferred repository pattern I use. Returning IQueryable means that my consumers can take advantage of deferred execution to decide how the details will be used, resulting in more efficient queries. (I.e. using .Select() to get the fields they want, doing .Count() or .Any(), .FirstOrDefault(), or .Skip().Take() etc.)
alternatively you might use generic repositories:
public interface IRepository<Order>
{
Order GetOrderById (int orderId);
ICollection<Order> GetOrdersForCustomer (int customerId);
}
The repository methods would contain minimal to no business logic. In my case the repository would only be concerted with:
Authorization (retrieve data based on the current user / tenant)
Active / Soft-Delete state. (retrieve "active" data in a soft-delete environment unless told otherwise.)
Temporal state. (Retrieve "current" date unless told otherwise.)
All business logic should reside in your service classes or controllers, where it can be tested in isolation. To test the above 3 conditions (if applicable) I use integration tests. These conditions are very low-level checks and would not change on any regular basis.
Lets say the code under test is in a Controller.
public class OrderController : IOrderController
{
private readonly IOrderRepository _repository = null;
private readonly IUnitOfWorkFactory _uowFactory = null;
public OrderController(IUnitOfWorkFactory uowFactory, IOrderRepository repository)
{
if (uowFactory == null)
throw new ArgumentNullException("uowFactory");
if (repository == null)
throw new ArgumentNullException("repository");
_uowFactory = uowFactory;
_repository = repository;
}
public void SomeActionOnOrder(int orderId)
{
using (var unitOfWork = _uowFactory.Create())
{
var order = _repository.GetOrderById(orderId)
// Here lies your validation checks that the order was found,
// business logic to do your behaviour.. This is the stuff you want to test..
// ...
unitOfWork.Commit();
}
}
}
Now when you go to test your controller...
[Test]
public void EnsureSomeActionOnOrderDoesIt()
{
var uowMock = new Mock<IUnitOfWork>();
var uowFactoryMock = new Mock<IUnitOfWorkFactory>();
var repositoryMock = new Mock<IOrderRepository>();
var testOrderId = -1;
var stubOrders = new [] { newOrder { /* populate expected data... */ } };
uowMock.Setup(x=>x.Commit());
uowFactoryMock.Setup(x=>x.Create()).Returns(uowMock.Object);
repositoryMock.Setup(x=>x.GetOrderById(testOrderId)).Returns(stubOrders.AsQueryable());
var testController = new OrderController(uowFactoryMock.Object, repositoryMock.Object);
testController.SomeActionOnOrder(testOrderId);
// Everything "touched" as expected? (did the code fetch the object? did it save the changes?)
uowFactoryMock.VerifyAll();
uowMock.VerifyAll();
repositoryMock.VerifyAll();
// Perform asserts on your stub order if SomeAction modified state as you expected.
}
Integration tests against an actual database would handle any logic that the repositories would be expected to cover.
The repository pattern I have above is the IQueryable flavour, alternatively if you return an entity, just return the "stubs" with a stub order and return it.
The mocking framework I use is Moq. The above code may not be fully syntactically correct, based solely on memory. :)
The goal of unit tests, as far as TDD/BDD go, is that these tests should be reliably repeatable, and fast to execute so that they can be run repeatedly and frequently as you are developing. Keeping repositories relatively thin, and not touching on the business logic decisions means that they can serve as a reliable cut-off point for unit tests to mock out. The repository's job is to return data, so by mocking at that point it means we can control the data we expect the code under test to work with. We can mock it to return objects, null, throw exceptions, whatever our test scenario expects our code under test to handle.
In the above example I also demonstrate the use of a basic Unit of Work pattern which wraps the DB Context. The implementation that I use for EF is Medhime's DB Context Scope Factory/Locator. Using the Unit of Work pattern we also have mocks that can verify that the code under test is (or is not) saving data for instance. The repository would need to have a link to a unit of work (initialized in a constructor, or "located" as-per the Mehdime pattern) but we don't care about that aspect when testing our services & controllers, the repository is merely mocked out and its purpose is to return and (optionally) create data.
I'll have my repositories serve as factories for entities (I.e. CreateOrder() with list of product details & quantities) to ensure that new entities are initialized with all expected referential links and required data rather than relying on calling code. That calling code would have to be littered with extra queries etc. to retrieve referential data for a new order, so instead I have it pass the view model data through to the Order Repository to resolve, wire-up, and return a valid new Order entity.
In a recent project, I created an extension method of a List<T> (could be IEnumerable, or whatever).
public static Mock<DbSet<T>> MockList<T>(this List<T> list) where T: class
{
var mockDbSet = new Mock<DbSet<T>>();
var queryable = list.AsQueryable();
mockDbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockDbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockDbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockDbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
return mockDbSet;
}
It is then quite simple to call.
var myData = new List<MyDataType> { new MyDataType(), new MyDataType(), ....};
var mockDb = new Mock<MyContext>();
mockDb.Setup(x => x.MyDatas).Returns(myData.MockList().Object);

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.

Using Methods not Defined in Interface on Fakes within Unit Tests

In my ViewModel, portions of functionality are enabled/disabled depending on the logged-in individual's permissions. The ViewModel relies on a dependency-injected ISecurity object to check if a user has a specific permission. Different portions of functionality require different permissions.
public Interface ISecurity
{
bool UserHasPermision(int userId, string permission);
}
In my production code, the concrete implementation of ISecurity interacts with an external application which does not allow me to change an individual's permissions. I created a FakeSecurity class that would allow me to do this in unit tests.
class FakeSecurity: ISecurity
{
private Dictionary<int, List<string>> permissions = new Dictionary<int, List<string>>();
public bool UserHasPermission(int userId, string permission)
{
return permissions.ContainsKey(userId) &&
permissions[userId].Contains(permission);
}
//Not defined in ISecurity
public void SetPermission(int userId, string permission, bool hasPermission)
{
if (!permissions.ContainsKey(userId))
{
permissions[userId] = new List<string>();
}
List<string> userPermissions = permissions[userId];
if (hasPermission)
{
userPermissions.Add(permission);
}
else
{
userPermissions.Remove(permission);
}
}
}
The problem here is that SetPermission() is not defined in the ISecurity interface, so in order for my Unit Tests to set an individual's permissions I need to cast the ISecurity object registered with my IUnityContainer to a FakeSecurity object. I am told that my unit test should be ignorant of the specific type of implementation that is being used for a particular interface and that calling methods that are not defined in the interface is an anti-pattern.
[TestMethod]
public void UserDoesNotHavePermission()
{
// test setup
IUnityContainer iocContainer = GetIocContainer();
ISecurity sec = iocContainer.Resolve<ISecurity>(); //registered singleton
(sec as FakeSecurity).SetPermission(GetCurrentUser().Id, "Save Colors", false);
var viewModel = iocContainer.Resolve<MaintainColorsViewModel>(); //per-request
// asserts
Assert.IsFalse(viewModel.CanSave);
}
[TestMethod]
public void UserHasPermission()
{
// test setup
IUnityContainer iocContainer = GetIocContainer();
ISecurity sec = iocContainer.Resolve<ISecurity>(); //registered singleton
(sec as FakeSecurity).SetPermission(GetCurrentUser().Id, "Save Colors", true);
var viewModel = iocContainer.Resolve<MaintainColorsViewModel>(); //per-request
// asserts
Assert.IsTrue(viewModel.CanSave);
}
Is this a bad practice or not? I realize that I shouldn't cast my ISecurity instace to a particular type within my application code, but is this really an issue Unit Tests?
I am told that my unit test should be ignorant of the specific type of implementation
This is incorrect. It is completely normal and good practice to let tests use both fake implementations and the class under test directly.
You however, are using the DI container in your unit tests, and that actually is bad practice. Although the use of the DI container is okay when you're writing integration tests (since you want to test components in integration with other components), using the DI library in unit tests leads to hard to read and maintain tests. With unit tests, you test code in isolation. This means that you usually create the class under test by hand, and inject the required fake dependencies to get the test running.
I would therefore expect such unit test to look like this:
public void CanSave_CurrentUserHasNoPermission_ReturnsFalse() {
// Arrange
var noPermission = new FakeSecurity { CurrentUserHasPermission = false };
var viewModel = new MaintainColorsViewModel(noPermission);
// Act
bool actualResult = viewModel.CanSave;
// Assert
Assert.IsFalse(actualResult);
}
public void CanSave_CurrentUserHasPermission_ReturnsTrue() {
// Arrange
var hasPermission = new FakeSecurity { CurrentUserHasPermission = true };
var viewModel = new MaintainColorsViewModel(hasPermission);
// Act
bool actualResult = viewModel.CanSave;
// Assert
Assert.IsTrue(actualResult);
}
public void CanSave_Always_QueriesTheSecurityForTheSaveColorsPermission() {
// Arrange
var security = new FakeSecurity();
var viewModel = new MaintainColorsViewModel(security);
// Act
bool temp = viewModel.CanSave;
// Assert
Assert.IsTrue(security.RequestedPermissions.Contains("Save Colors"));
}
There are a few things to note about this code:
Both the FakeSecurity and the MaintainColorsViewModel are created directly in the tests here; no DI library is used. This makes the tests much more readable and maintainable (and faster).
I considerably simplified the FakeSecurity class (shown below), because you want fake classes to be as simple as possible.
A third test is added to check explicitly whether the MaintainColorsViewModel requests the expected permission.
The AAA pattern (Arrange/Act/Assert) is implemented explicitly.
To allow these tests to be written the way they are, the following change has been made to the ISecurity abstraction:
interface ISecurity
{
bool UserHasPermission(string permission);
}
The userId parameter has been removed from the UserHasPermission method. The reason for this is that the ISecurity implementation will be able to find out who the current user is by itself. Allowing consumers of ISecurity to pass this parameter along only means that the API is getting more complex, there is more code to write, there's a bigger chance of programming errors, and we therefore need more supporting tests. In other words, the sole addition of this userId property forces a lot of extra production and test code to write and maintain.
Here is the simpflified FakeSecurity class:
class FakeSecurity : ISecurity
{
public bool CurrentUserHasPermission;
public List<string> RequestedPermissions = new List<string>();
public bool UserHasPermission(string permission)
{
this.RequestedPermissions.Add(permission);
return this.CurrentUserHasPermission;
}
}
The FakeSecurity class now has very little code and that makes it, just by looking at it, very easy to check for correctness. Remember, test code should be as simple as possible. Side note: replacing this class with a generated mock object, doesn't make our code easier. In most cases it will actually make our unit tests harder to read, understand and maintain.
One reason for developers to start using a DI container inside their unit tests is because the manual creation of the class under test (with all its fake dependencies) causes maintenance issues in their tests. This is true actually; if the MaintainColorsViewModel has multiple dependencies, and we would create that MaintainColorsViewModel in each test, the addition of a single dependency would cause us to change all our MaintainColorsViewModel tests. This often is a reason for developers to either use a DI container -or- revert to mocking frameworks.
This however is not a good reason to start using a DI container or mocking library. A simple refactoring can completely remove the maintenance problem; we just have to create a factory method as follows:
private static MaintainColorsViewModel CreateViewModel(params object[] dependencies) {
return new MaintainColorsViewModel(
dependencies.OfType<ISecurity>().SingleOrDefault() ?? new FakeSecurity(),
dependencies.OfType<ILogger>().SingleOrDefault() ?? new FakeLogger(),
dependencies.OfType<ITimeProvider>().SingleOrDefault() ?? new FakeTimeProvider(),
dependencies.OfType<IUserContext>().SingleOrDefault() ?? new FakeUserContext());
}
Here I assume that the MaintainColorsViewModel contains 4 dependencies (namely ISecurity, ILogger, ITimeProvider and IUserContext). The CreateViewModel factory method allows passing in all dependencies using a params array, and the method tries to get each abstraction from the array and when missing replaces it with the default fake implementation.
With this factory, we can now rewrite our tests to the following:
[TestMethod]
public void CanSave_CurrentUserHasNoPermission_ReturnsFalse()
{
// Arrange
var noPermission = new FakeSecurity { CurrentUserHasPermission = false };
MaintainColorsViewModel viewModel = CreateViewModel(noPermission);
// Act
bool actualResult = viewModel.CanSave;
// Assert
Assert.IsFalse(actualResult);
}
Or we can pass in multiple dependencies if the test requires this:
[TestMethod]
public void CanSave_CurrentUserHasNoPermission_LogsWarning()
{
// Arrange
var logger = new FakeLogger();
var noPermission = new FakeSecurity { CurrentUserHasPermission = false };
MaintainColorsViewModel viewModel = CreateViewModel(logger, noPermission);
// Act
bool temp = viewModel.CanSave;
// Assert
Assert.IsTrue(logger.Entries.Any());
}
Do note that this test is just here for educational purposes. I don't suggest the view model to actually do the logging; that should not be its responsibility.
The moral of the story here is actually that good design can simplify your testing efforts considerably to the point that you can write less code and less tests, while improving the quality of your software.
You shouldn't use a DI container in unit tests, see the answer in this question.
In unit tests, the object graph that you are testing is usually small (usually a single class). So you don't need a DI container.
Without a container, here is how your test would look like:
//Arrange
FakeSecurity fake_security = new FakeSecurity();
fake_security.SetPermission(GetCurrentUser().Id, "Save Colors", false);
MaintainColorsViewModel sut = new MaintainColorsViewModel(fake_security);
//Act
...
Please note that I am assuming that you are using constructor injection to inject ISecurity into MaintainColorsViewModel.
Please note that instead of creating a FakeSecurity class, you can use auto-generated mocks by using mocking frameworks. Here is a link to one of the mocking frameworks called FakeItEasy.
Based on my experience, when you feel something not natural in Unit Test, you may want to re-factor your code.
According to this code, there are a couple choices.
Define the permission dictionary as a property in the interface. So it is easy to set values at unit testing.
Define a permission layer, IPermission, to add/retrieve/remove permission. Then you can mock IPermission in unit testing your Security implementation.
At least I would define the SetPermission method in ISecurity, your current code does not let you define an ISecurity object and let you set permission. Think the following code.
{
ISecurity sec = CreateSecurity()
sec.SetPermission() // ERROR, SetPermission is not a method in ISecurity.
}
private ISecurity CreateSecurity()
{
return new Security()
}
However, I am not sure how to unit test in this case on top of my head.

How to unit test web service with Linq

I have a web service, which I would like to do some unit testing on, however I am not sure how I can do this. Can anyone give any suggestions? Below is the webservice, it produces an object with three fields, but only when there is values in the database queue.
[WebMethod]
public CommandMessages GetDataLINQ()
{
CommandMessages result;
using (var dc = new TestProjectLinqSQLDataContext())
{
var command = dc.usp_dequeueTestProject();
result = command.Select(c => new CommandMessages(c.Command_Type, c.Command, c.DateTimeSent)).FirstOrDefault();
return result;
}
}
You don't need to consume your data over the WebService to Unit test it. You can just create another project in your solution with a reference to your WebService project and call directly the methods.
First up, what you've posted can't really be Unit Tested at all; by definition, a Unit Test can have only a single reason to fail; However in your case, a single test of GetDataLINQ() (the "System Under Test" or "SUT") could fail because of a problem with any of the dependencies in the function - namely, TestProjectLinqSQLDataContext and usp_dequeueTestProject.
When you call this method from a Unit test, these dependencies at present are probably beyond your control because you didn't directly create them - they are most likely created in your page classes' constructor. (Note: this is an assumption on my part, and I could be wrong)
Also, because these dependencies are at present real "live" objects, which have hard dependencies on an actual database being present, it means your tests aren't able to run independently, which is another requirement for a Unit Test.
(I'll assume your page's class file is "MyPageClass" from now on, and I will pretend it's not a web page code-behind or asmx code-behind; because as other posters have pointed out, this only matters in the context of accessing the code via HTTP which we're not doing here)
var sut = new MyPageClass(); //sut now contains a DataContext over which the Test Method has no control.
var result = sut.GetDataLINQ(); //who know what might happen?
Consider some possible reasons for failure in this method when you call sut.GetDataLINQ():
new TestProjectLinqSQLDataContext() results in an exception because of a fault in TestProjectLinqSQLDataContext's constructor
dc.usp_dequeueTestProject() results in an exception because the database connection fails, or because the stored procedure has changed, or doesn't exist.
command.Select(...) results in an exception because of some as of yet unknown defect in the CommandMessage constructor
Probably many more reasons (i.e failure to perform correctly as opposed to an exception being thrown)
Because of the multiple ways to fail, you can't quickly and reliably tell what went wrong (certainly your test runner will indicate what type of exception threw, but that requires you to at least read the stack trace - you shouldn't need to do this for a Unit Test)
So, in order to do this you need to be able to setup your SUT - in this case, the GetDataLINQ function - such that any and all dependencies are fully under the control of the test method.
So if you really want to Unit Test this, you'll have to make some adjustments to your code. I'll outline the ideal scenario and then one alternative (of many) if you can't for whatever reason implement this. No error checking included in the code below, nor is it compiled so please forgive any typos, etc.
Ideal scenario
Abstract the dependencies, and inject them into the constructor.
Note that this ideal scenario will require you to introduce an IOC framework (Ninject, AutoFAC, Unity, Windsor, etc) into your project. It also requires a Mocking framework (Moq, etc).
1. Create an interface IDataRepository, which contains a method DequeueTestProject
public interface IDataRepository
{
public CommandMessages DequeueTestProject();
}
2. Declare IDataRepository as a dependency of MyPageClass
public class MyPageClass
{
readonly IDataRepository _repository;
public MyPageClass(IDataRepository repository)
{
_repository=repository;
}
}
3. Create an actual implementation of IDataRepository, which will be used in "real life" but not in your Unit Tests
public class RealDataRepository: IDataRepository
{
readonly MyProjectDataContext _dc;
public RealDataRepository()
{
_dc = new MyProjectDataContext(); //or however you do it.
}
public CommandMessages DequeueTestProject()
{
var command = dc.usp_dequeueTestProject();
result = command.Select(c => new CommandMessages(c.Command_Type, c.Command, c.DateTimeSent)).FirstOrDefault();
return result;
}
}
This is where you will need to involve your IOC framework such that it can inject the correct IDataRepository (i.e RealDataRepository) whenever your MyPageClass is instantiated by the ASP.NET framework
4. Recode your GetDataLINQ() method to use the _repository member
public CommandMessages GetDataLINQ()
{
CommandMessages result;
return _repository.DequeueTestProject();
}
So what has this bought us? Well, consider now how you can test against the following specification for GetDataLINQ:
Must always invoke DequeueTestProject
Must return NULL if there is no data in the database
Must return a valid CommandMessages instance if there is data in the database.
Test 1 - Must always invoke DequeueTestProject
public void GetDataLINQ_AlwaysInvokesDequeueTestProject()
{
//create a fake implementation of IDataRepository
var repo = new Mock<IDataRepository>();
//set it up to just return null; we don't care about the return value for now
repo.Setup(r=>r.DequeueTestProject()).Returns(null);
//create the SUT, passing in the fake repository
var sut = new MyPageClass(repo.Object);
//call the method
sut.GetDataLINQ();
//Verify that repo.DequeueTestProject() was indeed called.
repo.Verify(r=>r.DequeueTestProject(),Times.Once);
}
Test 2 - Must return NULL if there is no data in the database
public void GetDataLINQ_ReturnsNULLIfDatabaseEmpty()
{
//create a fake implementation of IDataRepository
var repo = new Mock<IDataRepository>();
//set it up to return null;
repo.Setup(r=>r.DequeueTestProject()).Returns(null);
var sut = new MyPageClass(repo.Object);
//call the method but store the result this time:
var actual = sut.GetDataLINQ();
//Verify that the result is indeed NULL:
Assert.IsNull(actual);
}
Test 3 - Must return a valid CommandMessages instance if there is data in the database.
public void GetDataLINQ_ReturnsNCommandMessagesIfDatabaseNotEmpty()
{
//create a fake implementation of IDataRepository
var repo = new Mock<IDataRepository>();
//set it up to return null;
repo.Setup(r=>r.DequeueTestProject()).Returns(new CommandMessages("fake","fake","fake");
var sut = new MyPageClass(repo.Object);
//call the method but store the result this time:
var actual = sut.GetDataLINQ();
//Verify that the result is indeed NULL:
Assert.IsNotNull(actual);
}
Because we can Mock the IDataRepository interface, therfore we can completely control how it behaves.
We could even make it throw an exception, if we needed to test how GetDataLINQ responds to unforseen results.
This is the real benefit of abstracting your dependencies when it comes to Unit Testing (not to mention, it reduces coupling in your system because dependencies are not tied to a particular concrete type).
Not Quite ideal method
Introducing an IOC framework into your project may be a non-runner, so here is one alternative which is a compromise. There are other ways as well, this is just the first that sprang to mind.
Create the IDataRepository interface
Create the RealDataRepository class
Create other implementations of IDataRepository, which mimic the behaviour we created on the fly in the previous example. These are called stubs, and basically they are just classes with a single, predefined behaviour that never changes. This makes then ideal for testing, because you always know what will happen when you invoke them.
public class FakeEmptyDatabaseRepository:IDataRepository
{
public CommandMessages DequeueTestProject(){CallCount++;return null;}
//CallCount tracks if the method was invoked.
public int CallCount{get;private set;}
}
public class FakeFilledDatabaseRepository:IDataRepository
{
public CommandMessages DequeueTestProject(){CallCount++;return new CommandMessages("","","");}
public int CallCount{get;private set;}
}
Now modify the MyPageClass as per the first method, except do not declare IDataRepository on the constructor, instead do this:
public class MyPageClass
{
private IDataRepository _repository; //not read-only
public MyPageClass()
{
_repository = new RealDataRepository();
}
//here is the compromise; this method also returns the original repository so you can restore it if for some reason you need to during a test method.
public IDataRepository SetTestRepo(IDataRepository testRepo)
{
_repository = testRepo;
}
}
And finally, modify your unit tests to use FakeEmptyDatabaseRepository or FakeFilledDatabaseRepository as appropriate:
public void GetDataLINQ_AlwaysInvokesDequeueTestProject()
{
//create a fake implementation of IDataRepository
var repo = new FakeFilledDatabaseRepository();
var sut = new MyPageClass();
//stick in the stub:
sut.SetTestRepo(repo);
//call the method
sut.GetDataLINQ();
//Verify that repo.DequeueTestProject() was indeed called.
var expected=1;
Assert.AreEqual(expected,repo.CallCount);
}
Note that this second scenario is not an ivory-tower-ideal scenario and doesn't lead to strictly pure Unit tests (i.e if there were a defect in FakeEmptyDatabaseRepository your test could also fail) but it's a pretty good compromise; however if possible strive to achieve the first scenario as it leads to all kinds of other benefits and gets you one step closer to truly SOLID code.
Hope that helps.
I would change your Code as follows:
public class MyRepository
{
public CommandMessage DeQueueTestProject()
{
using (var dc = new TestProjectLinqSQLDataContext())
{
var results = dc.usp_dequeueTestProject().Select(c => new CommandMessages(c.Command_Type, c.Command, c.DateTimeSent)).FirstOrDefault();
return results;
}
}
}
Then code your Web Method as:
[WebMethod]
public CommandMessages GetDataLINQ()
{
MyRepository db = new MyRepository();
return db.DeQueueTestProject();
}
Then Code your Unit Test:
[Test]
public void Test_MyRepository_DeQueueTestProject()
{
// Add your unit test using MyRepository
var r = new MyRepository();
var commandMessage = r.DeQueueTestProject();
Assert.AreEqual(commandMessage, new CommandMessage("What you want to compare"));
}
This allows your code to be reusable and is a common design pattern to have Data Repositories. You can now use your Repository Library everywhere you need it and test it in only one place and it should be good everywhere you use it. This way you don't have to worry about complicated tests calling WCF Services. This is a good way of testing Web Methods.
This is just a short explanation and can be improved much more, but this gets you in the right direction in building your Web Services.

How to perform Unit Testing on Create method in MVC?

How to perform a Unit testing on MVC application?
I have created the Controller Location.
It has properties like LocationName,Area,City,PinCode.
Now, I want to perform unit test to check whether Location saves in DB or not.
How to check it.
I have go through tons of videos, every where they just put the Unit test of
Mathematical operations like adding,Dividing , subtracting....
I would like to know how to perform the Unit testing of Create method of MVC
I have code something like below
[HttpPost]
public ActionResult Create(Location location)
{
if (ModelState.IsValid)
{
db.Locations.Add(location);
db.SaveChanges();
return RedirectToAction("Index");
}
}
In order to make your code testable, you should abstract dependencies of controller. It's very handy to use Repository pattern to abstract data access. Inject your repository into controller:
public class LocationController : Controller
{
private ILocationRepository _locationRepository;
public LocationController(ILocationRepository locationRepository)
{
_locationRepository = locationRepository;
}
}
Now you can mock your repository. Here is sample test with Moq framework and MvcContrib:
// Arrange
Mock<ILocationRepository> repository = new Mock<ILocationRepository>();
var controller = new LocationController(repository.Object);
Location location = new Location("New York);
// Act
var result = controller.Create(location);
// Assert
result.AssertActionRedirect()
.ToAction<LocationController>(c => c.Index());
repository.Verify(r => r.Add(location));
repository.Verify(r => r.Save());
And you can implement code, which will pass this test:
[HttpPost]
public ActionResult Create(Location location)
{
if (ModelState.IsValid)
{
_locationRepository.Add(location);
_locationRepository.Save();
return RedirectToAction("Index");
}
}
You can read more on implementing repositories and testing MVC applications here:
Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application. Nice feature also to have Unit of Work per request.

Categories

Resources