Machine.Fakes how to test virtual method implementation? - c#

Given I have a controller class as such:
public class ResourceController : AuthorizedController
{
public virtual string Resource()
{
//do magic
}
public virtual string ResourceParent()
{
var url = Resource();
return url;
}
}
}
With the test harness:
[Subject(typeof (ResourceController))]
public class When_I_want_the_parent_resource : WithSubject<ResourceController>
{
private static readonly string ParentUrl = "/organizations/1";
private static readonly string ResourceUrl = "/organizations/1/contacts/1";
private static string _result;
private Establish context = () =>
{
The<ResourceController>()
.WhenToldTo(x => x.Resource())
.Return(ResourceUrl);
};
private Because of = () => _result = Subject.ResourceParent();
private It should_match_the_expected_parent_url = () =>
_result.ShouldEqual(ParentUrl);
}
This unit test will fail because Subject.ResourceParent() will return null because Machine.Fakes has automocked this method. As a temporary workaround I just removed the virtual keyword from ResourceParent to be able to test my code. I assume there has to be a real solution for me to tell Machine.Fakes to not override ResourceParent()

actually there isn't a "real" solution in Machine.Fakes for this. I would argue that you need to reconsider you're fixture design.
First of all, as Tim already pointed out, you you should't fake any methods on the subject itself. Instead you should fake the dependencies of your controller and use your controller as-is in specifications. The intended usage of the "The" method is to access the dependencies of the subject under specification, but what you try in your spec is to access the subject itself. I think that's where things go wrong. The <ResourceController> and subject are actually separate instances. That's why you configured interaction doesn't happen.
Just some options to fix this in your code:
Introduce a new dependency in your code which you can stub via "The"
If the first seems to heavyweight, you could also replace the virtual method with a Func<string> dependency for your controller and use the "Configure" method to inject a specification specific one for your spec.
HTH,
Bjoern

If you're testing a controller, then perhaps you shouldn't be creating mocks or fakes of that controller. Otherwise you're just testing a mock and the test doesn't really have any validity.
Mock or fake the dependencies of the controller. Test the real controller.

In the end I ended up pulling this test out of Machine.Fakes and put it into a regular unit test. Then I just used Moq directly to configure the HttpRequestBase to seed data I needed and then just manually created my controller class and invoked methods on it.

Related

Unit Testing a controller that uses windows authentication

-------Please see updates below as I now have this set up for dependency injection and the use of the MOQ mocking framework. I'd still like to split up my repository so it doesn't directly depend on pulling the windowsUser within the same function.
I have a Web API in an intranet site that populates a dropdown. The query behind the dropdown takes the windows username as a parameter to return the list.
I realize I don't have all of this set up correctly because I'm not able to unit test it. I need to know how this "should" be set up to allow unit testing and then what the unit tests should look like.
Additional info: this is an ASP.NET MVC 5 application.
INTERFACE
public interface ITestRepository
{
HttpResponseMessage DropDownList();
}
REPOSITORY
public class ExampleRepository : IExampleRepository
{
//Accessing the data through Entity Framework
private MyDatabaseEntities db = new MyDatabaseEntities();
public HttpResponseMessage DropDownList()
{
//Get the current windows user
string windowsUser = HttpContext.Current.User.Identity.Name;
//Pass the parameter to a procedure running a select query
var sourceQuery = (from p in db.spDropDownList(windowsUser)
select p).ToList();
string result = JsonConvert.SerializeObject(sourceQuery);
var response = new HttpResponseMessage();
response.Content = new StringContent(result, System.Text.Encoding.Unicode, "application/json");
return response;
}
}
CONTROLLER
public class ExampleController : ApiController
{
private IExampleRepository _exampleRepository;
public ExampleController()
{
_exampleRepository = new ExampleRepository();
}
[HttpGet]
public HttpResponseMessage DropDownList()
{
try
{
return _exampleRepository.DropDownList();
}
catch
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
}
UPDATE 1
I have updated my Controller based on BartoszKP's suggestion to show dependency injection.
UPDATED CONTROLLER
public class ExampleController : ApiController
{
private IExampleRepository _exampleRepository;
//Dependency Injection
public ExampleController(IExampleRepository exampleRepository)
{
_exampleRepository = exampleRepository;
}
[HttpGet]
public HttpResponseMessage DropDownList()
{
try
{
return _exampleRepository.DropDownList();
}
catch
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
}
}
UPDATE 2
I have decided to use MOQ as a mocking framework for unit testing. I'm able to test something simple, like the following. This would test a simple method that doesn't take any parameters and doesn't include the windowsUser part.
[TestMethod]
public void ExampleOfAnotherTest()
{
//Arrange
var mockRepository = new Mock<IExampleRepository>();
mockRepository
.Setup(x => x.DropDownList())
.Returns(new HttpResponseMessage(HttpStatusCode.OK));
ExampleController controller = new ExampleController(mockRepository.Object);
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
//Act
var response = controller.DropDownList();
//Assert
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
I need help testing the DropDownList method (one that does include code to get the windowsUser). I need advice on how to break this method apart. I know both parts shouldn't been in the same method. I don't know how to arrange splitting out the windowsUser variable. I realize this really should be brought in as a parameter, but I can't figure out how.
You usually do not unit-test repositories (integration tests verify if they really persist the data in the database correctly) - see for example this article on MSDN:
Typically, it is difficult to unit test the repositories themselves, so it is often better to write integration tests for them.
So, let's focus on testing only the controller.
Change the controller to take IExampleRepository in its constructor as a parameter:
private IExampleRepository _exampleRepository;
public ExampleController(IExampleRepository exampleRepository)
{
_exampleRepository = exampleRepository;
}
Then, in your unit tests, use one of mocking frameworks (such as RhinoMock for example) to create a stub for the sole purpose of testing the controller.
[TestFixture]
public class ExampleTestFixture
{
private IExampleRepository CreateRepositoryStub(fake data)
{
var exampleRepositoryStub = ...; // create the stub with a mocking framework
// make the stub return given fake data
return exampleRepositoryStub;
}
[Test]
public void GivenX_WhenDropDownListIsRequested_ReturnsY()
{
// Arrange
var exampleRepositoryStub = CreateRepositoryStub(X);
var exampleController = new ExampleController(exampleRepositoryStub);
// Act
var result = exampleController.DropDownList();
// Assert
Assert.That(result, Is.Equal(Y));
}
}
This is just a quick&dirty example - CreateRepositoryStub method should be of course extracted to some test utility class. Perhaps it should return a fluent interface to make the test's Arrange section more readable on what is given. Something more like:
// Arrange
var exampleController
= GivenAController()
.WithFakeData(X);
(with better names that reflect your business logic of course).
In case of ASP.NET MVC, the framework needs to know how to construct the controller. Fortunately, ASP.NET supports the Dependency Injection paradigm and a parameterless constructor is not required when using MVC unity.
Also, note the comment by Richard Szalay:
You shouldn't use HttpContext.Current in WebApi - you can use base.User which comes from HttpRequestBase.User and is mockable. If you really want to continue using HttpContext.Current, take a look at Mock HttpContext.Current in Test Init Method
One trick that I find very useful when trying to make old code testable when said code is accessing some global static or other messy stuff that I can't easily just parameterize is to wrap access to the resource in a virtual method call. Then you can subclass your system under test and use that in the unit test instead.
Example, using a hard dependency in the System.Random class
public class Untestable
{
public int CalculateSomethingRandom()
{
return new Random().Next() + new Random().Next();
}
}
Now we replace var rng = new Random();
public class Untestable
{
public int CalculateSomethingRandom()
{
return GetRandomNumber() + GetRandomNumber();
}
protected virtual int GetRandomNumber()
{
return new Random().Next();
}
}
Now we can create a testable version of the class:
public class Testable : Untestable
{
protected override int GetRandomNumber()
{
// You can return whatever you want for your test here,
// it depends on what type of behaviour you are faking.
// You can easily inject values here via a constructor or
// some public field in the subclass. You can also add
// counters for times method was called, save the args etc.
return 4;
}
}
The drawback with this method is that you can't use (most) isolation frameworks to implement protected methods (easily), and for good reason, since protected methods are sort of internal and shouldn't be all that important to your unit tests. It's still a really handy way of getting things covered with tests so you can refactor them, instead of having to spend 10 hours without tests, trying to do major architectual changes to your code before you get to "safety".
Just another tool to keep in mind, I find it comes in handy from time to time!
EDIT: More concretely, in your case you might want to create a protected virtual string GetLoggedInUserName(). This will technically speaking keep the actual call to HttpContext.Current.User.Identity.Name untested, but you will have isolated it to the simplest smallest possible method, so you can test that the code is calling the correct method the right amount of times with the correct args, and then you simply have to know that HttpContext.Current.User.Identity.Name contains what you want. This can later be refactored into some sort of user manager or logged in user provider, you'll see what suits best as you go along.

Mocking HttpContext.server.MapPath in ASP.NET unit testing

I have working in unit testing in ASP.Net web application, now I have accessing my constructor in the model file to test which has Server.MapPath code for uploading my XMLfile, when try to testing this i get error, because the HttpContext is null so i have to mocking Server.MapPath.
I have searched lot but every samples given only for Asp.NET MVC but I have working in ASP.NET. so please help in ASP.NET to solve this issue.
My code is given below.
public class NugetPlatformModel
{
public bool IsHavingLicense { get; set; }
public List<PlatformProducts> PlatformProduct = new List<PlatformProducts>();
public NugetPlatformModel()
{
var xmldoc = new XmlDocument();
mldoc.Load(HttpContext.Current.Server.MapPath(#"~\Content\PlatformProducts.xml"));
}
}
And my unit testing code
[Test]
public void Account_UnlicensedCustomerIdentity_IsStudioLicenseAndIshavinglicenseFalse()
{
//Act
NugetPlatformModel nugetPlatformModel = new NugetPlatformModel();
//Assert
AssertEquals(false, nugetPlatformModel.IsHavingLicense);
}
This is typical with code that calls static methods, it's very difficult to test while preserving separation of concern and avoiding tight coupling. Here is a generic approach to test and mock "untestable code": write a "facade wrapper" to it.
Create a wrapper for these methods. A simple class that contains methods named sensibly, and only delegates to the untestable calls (typically static calls)
Create an interface to that wrapper class
Instead of directly calling the untestable methods in your client code, use the wrapper (dependency-injected using the interface provided in step 2) and call normal methods on it.
In your unit-test, mock the wrapper with the behaviour you want.
This approach effectively reduces the coupling and separates the concerns that need to be separated. Of course, you still can't test the behaviour of the wrapper itself, but if it's simple enough (only delegating to the original calls) then it's not as big a problem.
Update:
Using shims to isolate your application from other assemblies for unit testing
Shim types are one of two technologies that the Microsoft Fakes Framework uses to let you easily isolate components under test from the environment. Shims divert calls to specific methods to code that you write as part of your test. Many methods return different results dependent on external conditions, but a shim is under the control of your test and can return consistent results at every call. This makes your tests much easier to write.
Use shims to isolate your code from assemblies that are not part of your solution. To isolate components of your solution from each other, we recommend that you use stubs.
How already answered, you should decouple your system
public class NugetPlatformModel
{
public bool IsHavingLicense { get; set; }
public List<PlatformProducts> PlatformProduct = new List<PlatformProducts>();
public NugetPlatformModel(IPlatformProductProvider provider)
{
var xmldoc = new XmlDocument();
//System.Web.HttpContext.Current.Server.MapPath(#"~\Content\PlatformProducts.xml")
xmldoc.Load(provider.Filepath);
}
public interface IPlatformProductProvider
{
string Filepath { get; }
}
public class PlatformProductProvider: IPlatformProductProvider
{
string _filepath;
public string Filepath
{
get { return _filepath; }
set { _filepath = value;}
}
public PlatformProductProvider(string path)
{
_filepath = path;
}
}
}
And your test could be:
[Test]
public void Account_UnlicensedCustomerIdentity_IsStudioLicenseAndIshavinglicenseFalse()
{
//Arrange
// using Moq
//var mock = new Mock<IPlatformProductProvider>();
//IPlatformProductProvider provider = mock.Object;
//provider.Filepath = "pippo.xml";
// otherwise
var provider = new PlatformProductProvider("pippo.xml");
//Act
NugetPlatformModel nugetPlatformModel = new NugetPlatformModel(provider);
//Assert
AssertEquals(false, nugetPlatformModel.IsHavingLicense);
}
If you can't modify the source code, try using shims (https://msdn.microsoft.com/en-us/library/hh549176.aspx).

Testing CRUD class.

I have some issue. Im writing some unit test in my project but i don't know how to test my CRUD methods.. Maybe they are not testable ;/
This is one of my methods:
public static void IncrementInvalidLoginColumn(string login)
{
User user;
using (DTContext context = new DTContext())
{
try
{
user = context.Users.Where(u => u.Login.CompareTo(login) == 0).FirstOrDefault();
if (user.InvalidLogins < 3)
{
user.InvalidLogins = user.InvalidLogins + 1;
}
context.SaveChanges();
}
catch
{
}
}
}
Maybe someone will have idea what should i do.
It depends on what you mean by "unit" test. If you don't want your test to hit the database then your method is not testable (or at least not without some refactoring).
If hitting the database is acceptable (which would actually be an integration test) then you can definitely test your method.
Here are some steps:
1. Arrange the initial data. You use an instance of the DTContext directly in the test to put the system in a predefined state (basically you write some user records in the database)
You run the method you want to test (which in fact uses its own instance of the DTContext)
You use DTContext again to read the user information directly from the database and assert that the InvalidLogins property has incremented.
You need to make sure you delete any data that you put in manually.
This is the gist of DI:
public class Example {
private IDatabaseGateway myDatabase;
public Example(IDatabaseGateway myDb) {
myDatabase = myDb;
}
public void DoStuff() {
...
myDatabase.GetData();
...
}
}
You give your business class an abstraction of the database via the constructor, that is you inject your dependencies in the class that needs them.
Once you have this in place, in production code you pass in the constructor a concrete instance of IDatabaseGateway that goes to the actual database.
In the case of a unit test you pass it a mock instance of the same interface. The mock is a special object that you can setup/configure to return what you want. Various libraries exist for mocking (an easy one is Moq).
However without modifying your code too much, it is better to stick with integration testing that hits the database. It will give you a simple and valid test.
Especially since there are some pitfalls in mocking the DbContext in EF (ex. some queries may not work when you will use them in production, testing updates in EF with mocks is a bit trickier).
Ok so i read all of your posts and they was very helpful.
I use MOQ framework and this is example how i do it.
This is how Liviu M. told me to do for example:
public class CRUDclass
{
private DTContext _context;
public CRUDclass(DTContext myObj)
{
_context = myObj;
}
}
We have CRUD Class which are doing operations directly on our database. We have constructor with one argument and private field. This our context :)
This is (for example) my method in CRUDclass:
public bool AddUser(User user)
{
try
{
_context.Users.Add(user);
_context.SaveChanges();
return true;
}
catch
{
return false;
}
}
Ovecourse he have our DTContext class witch DBSet becouse i using entity framework. And after that i am able to write some test method:
[TestMethod]
public void Should_Add_User()
{
var mockSet = new Mock<DbSet<User>>();
var mockContext = new Mock<DTContext>();
mockContext.Setup(m => m.Users).Returns(mockSet.Object);
var usrCRUD = new UserCRUD(mockContext.Object);
var usr = new User();
usr.Login = "Login_Name";
usr.Email = "loginName#test.com";
usr.Password = "***";
usr.InvalidLogins = 0;
usr.RememberID = 0;
usrCRUD.AddUser(usr);
mockSet.Verify(m => m.Add(It.Is<User>(arg => arg.Login == "Login_Name")));
mockContext.Verify(m => m.SaveChanges(), Times.Once());
}
At first a have to set my fake object (Mock>).
This test method checks if our user was added to Mock :)
I hope it can help somebody, if anything will be unclear please write a question :)
The idea of unit tests is to test your ifs, switches, etc., not the database operations.
In your case you need an interface that is an abstration of DTContext. In the simplest case it might look as the following.
public interface IObjectContext : IDisposable
{
IEnumerable<User> Users { get; }
}
In more complicated cases you may need to use IQueryable<T> or IObjectSet<T> instead of IEnumerable<T>.
Add a partial class declaration of DTContext and make it implement IObjectContext. Add a constructor to the class that contains the method IncrementInvalidLoginColumn with a parameter of type IObjectContext. Now you can inject any instance of IObjectContext instead of creating it in your class. This instance can be a DTContext or a mock for testing. Your class is ready to be tested without connection to a real database.
NB. In case of instances of IDisposable it's better to inject a Func<IObjectContext> instead of IObjectContext. Then you can create an instance for each operation and dispose it immediately after.
If there are CRUD operations in your code then I will recommend to use MOQ framework for unit testing. Below links are quite helpful:
Quick Start
Code Project
Ideally you would inject your DTContext rather than creating a new one every time that the method is called. That way you could mock that object in your unit test and verify that it is called as expected.
Your constructor would look something like:
private readonly IDTContext _context;
public CrudClass(IDTContext context)
{
_context = context
}
With your method now looking like
public static void IncrementInvalidLoginColumn(string login)
{
User user;
try
{
user = _context.Users.Where(u => u.Login.CompareTo(login) == 0).FirstOrDefault();
if (user.InvalidLogins < 3)
{
user.InvalidLogins = user.InvalidLogins + 1;
}
_context.SaveChanges();
}
catch
{
// Handle errors
}
}
And then in your test, if you were using a framework like Moq, you would basically script how that object would behave and test against that. For instance, setting up the mocked IDTContext to always return the same user for your Users collection and SaveChanges() method will write the number of invalid logins to a variable that you could then test against.

Dependency injection in .NET for a class not under test

I am testing the functionality of a StoreManager class which has a dependency on DataBaseConfiguration class.
public class StoreManager {
private DataBaseConfiguration dbConfig;
public void Store(string name) {
dbConfig.Store(name);
}
//other methods here
}
The StoreManager class stores to a database and the only way I can test if this method works fine is to query from the database. I have another class in production which does that..
public class QueryManager {
private DataBaseConfiguration dbConfig;
public string Query(QueryExpression expr) {
//query logic
string name = "somename";
return name;
}}
Eventhough I am concerned with testing only my StoreManager class it looks to me like I need to use the QueryManager class to test the storedvalues.
So I have a basic test case like this one...
[TestFixture]
public class StoreManagerTest {
[TestFixtureSetup]
public void Setup() {
DatabaseConfiguration dbConfig = new DatabaseConfiguration(/*test database details*/);
StoreManager sm = new StoreManager(dbConfig);
QueryManager qm = new QueryManager(dbConfig);
}
[Test]
public void TestStore_ValidStore() {
sm.Store("testname");
string queryResult = qm.Query(new QueryExpression("query_expr"));
Assert.AreSame(queryResult, "testname");
}}
As you can see, apart from the ClassUnderTest (which is StoreManager), the QueryManager class also has a dependency on DatabaseConfig.
I don't have a lot of logic inside the StoreManager class, it just delegates to the DataBaseConfig class to store (well actually there are some more classes involved in storing, its not the DataBaseConfig that actually stores the data.. but just for simplicity purpose, lets say so..)
I would like to know if there is a better way to handle this test without involving QueryManager at all?
Also is there a better way to inject the dependency on DataBaseConfiguration into the StoreManager class (considering that the DataBaseConfiguration class takes details about the connection string, etc., of the database to store the data into.. and I would like to pass in a test database rather than the production database connection string there).
To get the dependencies out of the way in testing the most common approach is to either use a handwritten stub or a mocking framework (i.e Moq or RhinoMocks).
Additionally you would have to enable users of the StoreManager class to pass in the DataBaseConfiguration dependency, otherwise you cannot stub it out w/o changing the code. Constructor injection as you do right now is common practice and a clean way to do this (this becomes more convenient if you use an IOC container when you have lots of dependencies), also see here.
If I understand you correctly, you just want to test that the StoreManager actually stores the value you pass to it, you are interested in the behavior of the StoreManager and its interactions with its dependency DataBaseConfiguration - right now you do that by querying the data store itself for verification.
Given that let's go through a bare-bones example using RhinoMocks - the only thing I changed was define the Store method in your DataBaseConfiguration class as virtual so RhinoMocks can override it.
//Arrange
string storeValue = "testname";
var dbConfigMock = MockRepository.GenerateMock<DataBaseConfiguration>();
dbConfigMock.Expect(x => x.Store(storeValue));
StoreManager sm = new StoreManager(dbConfigMock);
//Act
sm.Store(storeValue);
//Assert
dbConfigMock.AssertWasCalled(x => x.Store(storeValue));
This test verifies that the Store method was called on your DataBaseConfiguration class w/o any other dependencies - it tests the behavior of your StoreManager class. This test does not touch the DB nor does it affect any other classes.
Edit:
I'm not sure I understand the concern about using a mocking framework in production code - the mocking framework is only used in your test projects, no reference to it or any code changes are required to the production code itself.
Using a handwritten stub you can do the same assertions "manually": Define a test stub that stores how many times and with what value Store() was called (again this requires the Store method to be declared virtual so it can be overridden):
public class DataBaseConfigurationTest : DataBaseConfiguration
{
public int TimesCalled { get; set; }
public string LastNameStored { get; set; }
public DataBaseConfigurationTest()
{
TimesCalled = 0;
}
public override void Store(string name)
{
TimesCalled++;
LastNameStored = name;
}
}
Now use this test stub in your test instead of the "real" DataBaseConfiguration:
string storeValue = "testname";
DataBaseConfigurationTest dbConfigStub = new DataBaseConfigurationTest();
StoreManager sm = new StoreManager(dbConfigStub);
sm.Store(storeValue);
Assert.AreEqual(1, dbConfigStub.TimesCalled);
Assert.AreEqual(storeValue, dbConfigStub.LastNameStored);

Help/advice needed with unit testing repositories

I am using .NET 4, NUnit and Rhino mocks. I want to unit test my news repository, but I am not sure of how to go about it. My news repository is what I will eventually be using to communicate to the database. I want to use it to test against fake/dummy data. Not sure if it is possible?? This is what I currently have:
public interface INewsRepository
{
IEnumerable<News> FindAll();
}
public class NewsRepository : INewsRepository
{
private readonly INewsRepository newsRepository;
public NewsRepository(INewsRepository newsRepository)
{
this.newsRepository = newsRepository;
}
public IEnumerable<News> FindAll()
{
return null;
}
}
My unit test looks like this:
public class NewsRepositoryTest
{
private INewsRepository newsRepository;
[SetUp]
public void Init()
{
newsRepository = MockRepository.GenerateMock<NewsRepository>();
}
[Test]
public void FindAll_should_return_correct_news()
{
// Arrange
List<News> newsList = new List<News>();
newsList.Add(new News { Id = 1, Title = "Test Title 1" });
newsList.Add(new News { Id = 2, Title = "Test Title 2" });
newsRepository.Stub(r => r.FindAll()).Return(newsList);
// Act
var actual = newsRepository.FindAll();
// Assert
Assert.AreEqual(2, actual.Count());
}
}
In the above code I am not sure what I need to mock. The code above compiles but fails in the NUnit GUI about a contructor value. I can only assume it has to do with the INewsRepository paramter that I need to supply to NewsRepository. I don't know how to do this in the test. Can someone please rectify my unit test so that it will pass in the NUnit GUI? Can someone also provide some feedback on if I am implementing my repositories correctly?
Being a newbie to mocking, is there anything that I need to verify? When would I need to verify? What is its purpose? I have been working through a couple of source code projects and some use verify and some don't.
If the above test passes, what does this prove to me as developer? What does another developer have to do to my repository to make it fail in the NUnit GUI?
Sorry for all the questions, but they are newbie questions :)
I hope soomeone can help me out.
As Steven has said, you're Asserting against the Mock NewsRepository in the above code.
The idea of mocking is to isolate the Code Under Test and to create fakes to replace their dependencies.
You use the Mock NewsRepository to test something that uses INewsRepository, in your case, you mention NewsService; NewsService will use your mock of INewsRepository.
If you search your solution for anything that uses INewsRepository.FindAll(), you will create a Mock Repository to test that code in isolation.
If you want to test something that calls your Service layer, you will need to mock NewsService.
Also, as Steven as said, there is no need for the NewsRepository to have a copy of itself injected by IoC, so:
public class NewsRepository : INewsRepository
{
private readonly INewsRepository newsRepository;
public NewsRepository(INewsRepository newsRepository)
{
this.newsRepository = newsRepository;
}
public IEnumerable<News> FindAll()
{
return null;
}
}
should become:
public class NewsRepository : INewsRepository
{
public IEnumerable<News> FindAll()
{
return null;
}
}
Once you have functionality in your FindAll() method that needs testing, you can mock the objects that they use.
As a point of style from the great Art Of Unit Testing initialisation of mock objects is best left out of the Setup method and carried out in a helper method called at the start of the method. Since the call to Setup will be invisible and makes the initalisation of the mock unclear.
As another point of style, from that book, a suggested unit test naming convention is: "MethodUnderTest_Scenario_ExpectedBehavior".
So,
FindAll_should_return_correct_news
could become, for example:
FindAll_AfterAddingTwoNewsItems_ReturnsACollectionWithCountOf2
I hope this makes the approach clearer.
Your FindAll_should_return_correct_news test method is not testing the repository, it is testing itself. You can see this when you simplify it to what it really does:
[Test]
public void FindAll_should_return_correct_news()
{
// Arrange
List<News> newsList = new List<News>();
newsList.Add(new News { Id = 1, Title = "Test Title 1" });
newsList.Add(new News { Id = 2, Title = "Test Title 2" });
// Act
var actual = newsList;
// Assert
Assert.AreEqual(2, actual.Count());
}
As you can see, what you're basically doing is creating a list, filling it and testing if it actually contains the number of records that you put in it.
When your repository does nothing else than database interaction (so no application logic) there is nothing to test using a unit test. You can solve this problem by writing integration tests for the repositories. What you can basically do with such a integration test is insert some records in a test database (use a real database though, not an in-memory database) and then call the real repository class to see if it fetches the expected records from your test database. All should be executed within a transaction and rolled back at the end of the test (this ensures these tests keep trustworthy).
When you're using a O/RM tool that allows you to write LINQ queries, you could also try a different approach. You can fake your LINQ provider, as you can see in this article.
Might want to read over this post by ayende

Categories