I have method
public IEnumerable<string> LoadCountries()
{
try
{
return GetAll().GetCountries();
}
catch (Exception)
{
return null;
}
}
GetAll() method load data from sql server but I don't need it in test
So i changed database on IEnumerable customers. I wanna test it
Mock<ICustomersRepository> mock = new Mock<ICustomersRepository>();
mock.Setup(m => m.GetAll()).Returns(customers.AsQueryable()); //change data
IEnumerable<string> countries = mock.Object.LoadCountries();
Assert.AreEqual(countries.Count(), 6); //expect 6 countries
But in this test countries.Count() == 0;
Sure I can modify Mock Setup and add
mock.Setup(m => m.LoadCountries()).Returns(customers.AsQueryable().GetCountries());
But I don't want to do it, because other functions that i want to test are much bigger.
Is anyone know how can set GetAll() function to return my test array, even if GetAll() implements inside test class?
I just try to set
mock.CallBase = true;
mock.Setup(m => m.LoadCountries()).CallBase();
but i just see exception
System.NotImplementedException: This is a DynamicProxy2 error:
The interceptor attempted to 'Proceed' for method
'System.Collections.Generic.IEnumerable`1[System.String] LoadCountries()' which has no target.
When calling method without target there is no implementation to 'proceed' to and
it is the responsibility of the interceptor to mimic the implementation (set return
value, out arguments etc).
You are creating dymic proxy class which implements ICustomersRepository interface. Then you are exercising this generated proxy:
Mock<ICustomersRepository> mock = new Mock<ICustomersRepository>();
IEnumerable<string> countries = mock.Object.LoadCountries();
That is not very good idea. What do you verify with this test? Proxy generation? Proxy will not be used by your real code. You should use mocks to provide mocked dependencies for testing of real classes which are used by your application.
Actually I would not test that LoadCountries() calls GetAll() internally. Because this is a details of implementation, and that is not a business requirement for customers repository. I would write some acceptance/integration tests to verify that with given customers correct countries are returned.
UPDATE: Thus your GetCountries() filter is an extension, then you don't need to involve repository in its testing. Thats a simple static class, which can be tested on its own. BUT your test without interaction with database also will not be very valuable, because your extension composes query to datasource, which will be translated by query provider. I'll give you an example. If you have local method call (or method which canot be translated by your query provider):
public static class Extensions
{
public static IQueryable<string> GetCountries(this IQueryable<Customer> q)
{
return q.GroupBy(c => c.Country).Select(x => LocalMethod(x.Key));
}
private static string LocalMethod(string country)
{
return country.ToUpper();
}
}
Then following unit test will pass when you work with objects in-memory:
List<Customer> customers = new List<Customer> {
new Customer { Country = "USA" },
new Customer { Country = "Spain" }
};
var countries = Extensions.GetCountries(customers.AsQueryable());
Assert.AreEqual(countries.Count(), 2);
But when you'll run your application which queries SQL database with Entity Framework, then EF will fail to translate this filter into SQL.
But if you are trying to tests your repository and your LoadCountries is in your Repository layer, then you shouldn´t mock your repo.
you can´t use a repository method on a mock object ;) atleast without specifying some Return()
If you mock your repo is because you don´t want to connect to the database for the testa dn you want to retrieve mock data using for example:
List<Country> myList = //Fill your list with countries
repo.Setup(x => x.LoadCountries).Return(myList);
And then, use some other part to use this mock data.
But as I said, if you are trying to tests your repository, you shouldn´t mock it.
You mock your repository when you are trying to for example, tests some business part, and then you need some fake data from the database, the, mock the repo, and get you fake data ;)
If is this case, then:
Mock<ICustomersRepository> mock = new Mock<ICustomersRepository>();
mock.Setup(x => x.LoadCountries).Return(myList);
then for example, if from your business layer you ask in the constructor the ICustomersRepository, then you can create a instance f the business layer and pass this mock repo.
MyService service = new MyService(mock.Object);
service.LoadAll();
And if this LoadAll() use LoadCountries, then when this LoadAll call to LoadCountries it will get your mock data of countries!
I hope this helps!
Related
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);
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.
I'm brand new to unit testing and I need to do this for a current project. I have plenty of examples for testing model classes and MVC controllers, but I have a couple of web API controllers that have a Json return that I need to unit test. What should I be testing with these, and how can I do that?
First example taking no parameters
public class DefaultController : ApiController
{
private TestEntities db = new TestEntities();
[AcceptVerbs("GET")]
public IHttpActionResult FirstAPI()
{
var myQuery = (from p in db.Participants
select new
{
p.ID,
p.Name,
p.MemberType
});
return Json(myQuery);
}
}
Second example taking two parameters
public class DefaultController : ApiController
{
private TestEntities db = new TestEntities();
[AcceptVerbs("GET")]
public IHttpActionResult SecondAPI(int id, string name)
{
var myQuery = (from p in db.Participants
where p.ID == id && p.Name == name
select new
{
p.ID,
p.Name,
p.MemberType
});
return Json(myQuery);
}
}
You'd unit test it the same way you unit test anything... Invoke it and examine the results. In this case the result is of type HttpActionResult, which appears to have only one operation on it.
So your test will likely need to also invoke that operation, probably awaiting it since it's async, and examine the results of that which appear to be of type HttpResponseMessage.
That type has properties you can examine to validate the result of the operation you're testing. The most important property likely being Content, which contains the contents of the response. Your test will basically read those contents and validate them against an expected result.
The bigger problem here isn't actually validating the result, that's easy once you peer into the returned value as described above. The real problem with your unit test is this:
private TestEntities db = new TestEntities();
Your controller is tightly coupled to a dependency. Unless you have proper mocking set up within that dependency which isn't shown here, then your unit test will also be tightly coupled to that dependency.
Abstracting that dependency behind an interface and using dependency injection to de-couple your controller is highly recommended. That way your unit tests can supply a mock dependency with known, predictable behavior.
the code bellow run verry good for me :
var result = controller.Test(expectedArg) as JsonResult<MyClass>;
Assert.AreEqual(expectedResult, result.Content);
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.
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.