I have a service layer, which has a range of methods. These methods have implemented caching, like the following:
string key = "GetCategories";
if (CacheHandler.IsCachingEnabled() && !CacheHandler.ContainsKey(key))
{
var categories = RequestHelper.MakeRequest("get_category_index")["categories"];
var converted = categories.ToObject<List<Category>>();
CacheHandler.InsertToCache(key,converted);
return converted;
}
return CacheHandler.GetCache(key) as List<Category>;
Now, problem is I also want to make a unit test, like the following:
[TestMethod]
public void GetCategories()
{
IContentService contentService = new ContentService();
var resp = contentService.GetCategories();
Assert.IsNotNull(resp,"Should not be null");
}
Problem is, that the HttpContext.Current inside my CacheHandler is null during the unit test (obviously).
What is the easiest way to fix this?
(Please be as specific as possible because I haven't done a lot of unit testing before)
This screams dependency injection. The main problem I see is that you access the CacheHandler statically, so in a unit test, you:
a) cannot test the service without "testing" the CacheHandler as well
b) cannot supply any other CacheHandler to the service, for example a mocked one
If that's possible in your case, I'd either refactor or at least wrap the CacheHandler so that the service accesses an instance of it. In a unit test, you can then supply the service with a "fake" CacheHandler, that would not access HttpContext and also could give you a very fine control over the test itself (e.g. you can test what happens when an item is cached vs. when it isn't in two absolutely independent unit tests)
For the mocking part, I suppose it's easiest to create an interface and then use some automocking/proxy-generation framework designed for testing, for example Rhino Mocks (but there are many more, it just happens that I'm using this one and am very happy with it :)). Another approach (easier for a beginner, but more cumbersome in an actual development) would be simply to design the CacheHandler (or its wrapper) so that you can inherit from it and override the behaviour yourself.
Finally for the injection itself, I have found out a handy "pattern", which takes advantage of C# default method arguments and the standard constructor injection. The service constructor would look like:
public ContentService(ICacheHandler cacheHandler = null)
{
// Suppose I have a field of type ICacheHandler to store the handler
_cacheHandler = cacheHandler ?? new CacheHandler(...);
}
So in the application itself, I can call the constructor without parameters (or let frameworks construct the service, if it's ASP.NET handler, WCF service or some other kind of class) and in unit tests, I can supply whatever is implementing the said interface.
In case of Rhino Mocks, it can look like this:
var mockCacheHandler = MockRepository.GenerateMock<ICacheHandler>();
// Here I can mock/stub methods and properties, set expectations etc...
var sut = new ContentService(mockCacheHandler);
Dependency Injection as recommended in Honza Brestan's answer is certainly a valid solution, and maybe the best solution - especially if you might want to use something other than the ASP.NET Cache in the future.
However I should point out that you can use the ASP.NET Cache without needing an HttpContext. Instead of referencing it as HttpContext.Current.Cache, you can use the static property HttpRuntime.Cache.
This will enable you to use the Cache outside the context of an HTTP request, such as in a unit test or in a background worker thread. In fact I'd generally recommend using HttpRuntime.Cache for data caching in the business tier to avoid taking the dependency on the existence of an HttpContext.
Separate the cache into its own class, working like a proxy.
public interface IContentService
{
Categories GetCategories();
}
public class CachingContentService : IContentService
{
private readonly IContentService _inner;
public CachingContentSerice(IContentService _inner)
{
_inner = inner;
}
public Categories GetCategories()
{
string key = "GetCategories";
if (!CacheHandler.ContainsKey(key))
{
Catogories categories = _inner.GetCategories();
CacheHandler.InsertToCache(key, categories);
}
return CacheHandler.GetCache(key);
}
}
public class ContentSerice : IContentService
{
public Categories GetCategories()
{
return RequestHelper.MakeRequest("get_category_index")["categories"];
}
}
To enable caching, decorate the real ContentService with the cache:
var service = new CachingContentService(new ContentService());
To test the cache, create the CachingContentService with a test double as a constructor parameter. Use the test double to verify the cache: call it once and it should call the service behind. Call it twice and it should not call the service behind.
As a best practice, you only want to test one thing during a test and what you're describing has multiple steps. Therefore, it would be best to construct your test of your "RequestHelper.MakeRequest" and other routines so that they run their tests separately from the caching scenario. Testing them separately will let you know if their are problems in these routines or in the caching. You can integrate them later to test them as a group.
To test the caching separately, you can create a mock object to create the HttpContext with the properties that you need. Here are some previous answers that should help you put this together:
How do I mock the HttpContext in ASP.NET MVC using Moq?
Mock HttpContext.Current in Test Init Method
Related
I currently have a repository that is using Entity Framework for my CRUD operations.
This is injected into my service that needs to use this repo.
Using AutoMapper, I project the entity Model onto a Poco model and the poco gets returned by the service.
If my objects have multiple properties, what is a correct way to set-up and then assert my properties?
If my service has multiple repo dependencies what is the correct way to setup all my mocks? * - A class [setup] where all the mocks and objects are configured for these test fixtures?*****
I want to avoid having 10 tests and each test has 50 asserts on properties and dozens on mocks set-up for each test. This makes maintainability and readability difficult.
I have read Art of Unit Testing and did not discover any suggestions how to handle this case.
The tooling I am using is Rhino Mocks and NUnit.
I also found this on SO but it doesn't answer my question: Correctly Unit Test Service / Repository Interaction
Here is a sample that expresses what I am describing:
public void Save_ReturnSavedDocument()
{
//Simulate DB object
var repoResult = new EntityModel.Document()
{
DocumentId = 2,
Message = "TestMessage1",
Name = "Name1",
Email = "Email1",
Comment = "Comment1"
};
//Create mocks of Repo Methods - Might have many dependencies
var documentRepository = MockRepository.GenerateStub<IDocumentRepository>();
documentRepository.Stub(m => m.Get()).IgnoreArguments().Return(new List<EntityModel.Document>()
{
repoResult
}.AsQueryable());
documentRepository.Stub(a => a.Save(null, null)).IgnoreArguments().Return(repoResult);
//instantiate service and inject repo
var documentService = new DocumentService(documentRepository);
var savedDocument = documentService.Save(new Models.Document()
{
ID = 0,
DocumentTypeId = 1,
Message = "TestMessage1"
});
//Assert that properties are correctly mapped after save
Assert.AreEqual(repoResult.Message, savedDocument.Message);
Assert.AreEqual(repoResult.DocumentId, savedDocument.DocumentId);
Assert.AreEqual(repoResult.Name, savedDocument.Name);
Assert.AreEqual(repoResult.Email, savedDocument.Email);
Assert.AreEqual(repoResult.Comment, savedDocument.Comment);
//Many More properties here
}
First of all, each test should only have one assertion (unless the other validates the real one) e.q. if you want to assert that all elements of a list are distinct, you may want to assert first that the list is not empty. Otherwise you may get a false positive. In other cases there should only be one assert for each test. Why? If the test fails, it's name tells you exactly what is wrong. If you have multiple asserts and the first one fails you don't know if the rest was ok. All you know than is "something went wrong".
You say you don't want to setup all mocks/stubs in 10 tests. This is why most frameworks offer you a Setup method which runs before each test. This is where you can put most of your mocks configuration in one place and reuse it. In NUnit you just create a method and decorate it with a [SetUp] attribute.
If you want to test a method with different values of a parameter you can use NUnit's [TestCase] attributes. This is very elegant and you don't have to create multiple identical tests.
Now lets talk about the useful tools.
AutoFixture this is an amazing and very powerful tool that allows you to create an object of a class which requires multiple dependencies. It setups the dependencies with dummy mocks automatically, and allows you to manually setup only the ones you need in a particular test. Say you need to create a mock for UnitOfWork which takes 10 repositories as dependencies. In your test you only need to setup one of them. Autofixture allows you to create that UnitOfWork, setup that one particular repository mock (or more if you need). The rest of the dependencies will be set up automatically with dummy mocks. This saves you a huge amount of useless code. It is a little bit like an IOC container for your test.
It can also generate fake objects with random data for you. So e.q. the whole initialization of EntityModel.Document would be just one line
var repoResult = _fixture.Create<EntityModel.Document>();
Especially take a look at:
Create
Freeze
AutoMockCustomization
Here you will find my answer explaining how to use AutoFixture.
SemanticComparison Tutorial This is what will help you to avoid multiple assertions while comparing properties of objects of different types. If the properties have the same names it will to it almost automatically. If not, you can define the mappings. It will also tell you exactly which properties do not match and show their values.
Fluent assertions This just provides you a nicer way to assert stuff.
Instead of
Assert.AreEqual(repoResult.Message, savedDocument.Message);
You can do
repoResult.Message.Should().Be(savedDocument.Message);
To sum up. These tools will help you create your test with much less code and will make them much more readable. It takes time to get to know them well. Especially AutoFixture, but when you do, they become first things you add to your test projects - believe me :). Btw, they are all available from Nuget.
One more tip. If you have problems with testing a class it usually indicates a bad architecture. The solution usually is to extract smaller classes from the problematic class. (Single Responsibility Principal) Than you can easily test the small classes for business logic. And easily test the original class for interactions with them.
Consider using anonymous types:
public void Save_ReturnSavedDocument()
{
// (unmodified code)...
//Assert that properties are correctly mapped after save
Assert.AreEqual(
new
{
repoResult.Message,
repoResult.DocumentId,
repoResult.Name,
repoResult.Email,
repoResult.Comment,
},
new
{
savedDocument.Message,
savedDocument.DocumentId,
savedDocument.Name,
savedDocument.Email,
savedDocument.Comment,
});
}
There is one thing to look-out for: nullable types (eg. int?) and properties that might have slightly different types (float vs double) - but you can workaround this by casting properties to specific types (eg. (int?)repoResult.DocumentId ).
Another option would be to create a custom assert class/method(s).
Basically, the trick is to push as much clutter as you can outside of the unittests, so that only the behaviour
that is to be tested remains.
Some ways to do that:
Don't declare instances of your model/poco classes inside each test, but rather use a static TestData class that
exposes these instances as properties. Usually these instances are useful for more than one test as well.
For added robustness, have the properties on the TestData class create and return a new object instance every time
they're accessed, so that one unittest cannot affect the next by modifying the testdata.
On your testclass, declare a helper method that accepts the (usually mocked) repositories and returns the
system-under-test (or "SUT", i.e. your service). This is mainly useful in situations where configuring the SUT
takes more than 2 or more statements, since it tidies up your test code.
As an alternative to 2, have your testclass expose properties for each of the mocked Repositories, so that you don't need to declare these in your unittests; you can even pre-initialize them with a default behaviour to reduce the configuration per unittest even further.
The helper method that returns the SUT then doesn't take the mocked Repositories as arguments, but rather contstructs the SUT using the properties. You might want to reinitialize each Repository property on each [TestInitialize].
To reduce the clutter for comparing each property of your Poco with the corresponding property on the Model object, declare a helper method on your test class that does this for you (i.e. void AssertPocoEqualsModel(Poco p, Model m)). Again, this removes some clutter and you get the reusability for free.
Or, as an alternative to 4, don't compare all properties in every unittest, but rather test the mapping code in only one place with a separate set of unittests. This has the added benefit that, should the mapping ever include new properties or change
in any other way, you don't have to update 100-odd unittests.
When not testing the property mappings, you should just verify that the SUT returns the correct object instances (i.e. based on Id or Name), and that just the properties that might be changed (by the business logic being currently tested)
contain the correct values (such as Order total).
Personally, I prefer 5 because of its maintainability, but this isn't always possible and then 4 is usually a viable alternative.
Your test code would then look like this (unverified, just for demonstration purposes):
[TestClass]
public class DocumentServiceTest
{
private IDocumentRepository DocumentRepositoryMock { get; set; }
[TestInitialize]
public void Initialize()
{
DocumentRepositoryMock = MockRepository.GenerateStub<IDocumentRepository>();
}
[TestMethod]
public void Save_ReturnSavedDocument()
{
//Arrange
var repoResult = TestData.AcmeDocumentEntity;
DocumentRepositoryMock
.Stub(m => m.Get())
.IgnoreArguments()
.Return(new List<EntityModel.Document>() { repoResult }.AsQueryable());
DocumentRepositoryMock
.Stub(a => a.Save(null, null))
.IgnoreArguments()
.Return(repoResult);
//Act
var documentService = CreateDocumentService();
var savedDocument = documentService.Save(TestData.AcmeDocumentModel);
//Assert that properties are correctly mapped after save
AssertEntityEqualsModel(repoResult, savedDocument);
}
//Helpers
private DocumentService CreateDocumentService()
{
return new DocumentService(DocumentRepositoryMock);
}
private void AssertEntityEqualsModel(EntityModel.Document entityDoc, Models.Document modelDoc)
{
Assert.AreEqual(entityDoc.Message, modelDoc.Message);
Assert.AreEqual(entityDoc.DocumentId, modelDoc.DocumentId);
//...
}
}
public static class TestData
{
public static EntityModel.Document AcmeDocumentEntity
{
get
{
//Note that a new instance is returned on each invocation:
return new EntityModel.Document()
{
DocumentId = 2,
Message = "TestMessage1",
//...
}
};
}
public static Models.Document AcmeDocumentModel
{
get { /* etc. */ }
}
}
In general, if your having a hard time creating a concise test, your testing the wrong thing or the code your testing has to many responsibilities. (In my experience)
In specific, it looks like your testing the wrong thing here. If your repo is using entity framework, your getting the same object back that your sending in. Ef just updates to Id for new objects and any time stamp fields you might have.
Also, if you can't get one of your asserts to fail without a second assert failing, then you don't need one of them. Is it really possible for "name" to come back ok but for "email" to fail? If so, they should be in separate tests.
Finally, trying to do some tdd might help. Comment out all the could in your service.save. Then, write a test that fails. Then un comment out only enough code to make your test pass. Them write your next failing test. Can't write a test that fails? Then your done.
I have a number of controllers that I am testing, each of which has a dependency on a repository. This is how I am supplying the mocked repository in the case of each test fixture:
[SetUp]
public void SetUp()
{
var repository = RepositoryMockHelper.MockRepository();
controller = new HomeController(repository.Object);
}
And here is the MockRepository helper method for good measure:
internal static Mock<IRepository> MockRepository()
{
var repository = new Mock<IRepository>();
var posts = new InMemoryDbSet<Post>()
{
new Post {
...
},
...
};
repository.Setup(db => db.Posts).Returns(posts);
return repository;
}
... = code removed for the sake of brevity.
My intention is to use a new instance of InMemoryDbSet for each test. I thought that using the SetUp attribute would achieve this but clearly not.
When I run all of the tests, the results are inconsistent as the tests do not appear to be isolated. One test will for example, remove an element from from the data store and assert that the count has been decremented but according to the whim of the test runner, another test might have incremented the count, causing both tests to fail.
Am I approaching these tests in the correct way? How can I resolve this issue?
The package you reference you are using for your InMemoryDataSet uses a static backing data structure, and so will persist across test runs. This is why you're seeing the inconsistent behaviors. You can get around this by using another package (as you mention), or pass in a new HashSet to the constructor in every test so it doesn't use a static member.
As to the rest of your question, I think you're approaching the testing well. The only thing is that since all of your tests have the same setup (in your SetUp method), they could influence each other. I.e., if you have a test that relies on having no Foo objects in the set and one that needs at least one, then you're either going to add one in SetUp and remove it in the test that doesn't need it, or vice versa. It could be more clear to have specific set up procedures as #BillSambrone mentioned.
As #PatrickQuirk pointed out, I think your problem is due to what InMemoryDbSet does under the covers.
Regarding the "Am I approaching this right ?" part :
If, as I suspect, your Repository exposes some kind of IDbSet, it's probably a leaky abstraction. The contract of an IDbSet is far too specific for what a typical Repository client wants to do with the data. Better to return an IEnumerable or some sort of read-only collection instead.
From what you describe, it seems that consumers of Posts will manipulate it as a read-write collection. This isn't a typical Repository implementation - you'd normally have separate methods such as Get(), Add(), etc. The actual internal data collection is never exposed, which means you can easily stub or mock out just the individual Repository operations you need and not fear the kind of issues you had with your test data.
Whatever is in your [SetUp] method will be called for each test. This is probably behavior that you don't want.
You can either place the code you have in the [SetUp] method inside each individual test, or you can create a separate private method within your unit test class that will spin up a freshly mocked DbSet for you to keep things DRY.
It's often the case where I'd like to have multiple constructors in my controllers, since one of the constructors is optimal for manually injecting dependencies during unit testing and the other is optimal for using a IOC container to inject dependencies.
When using the standard service locator or DependencyResolver in MVC 3, is there any way to indicate to the controller factory which constructor to use when activating the controller?
I'd prefer not to use one of the attributes specific to an IOC framework since I want the code to remain independent of the IOC container.
UPDATE:
It seems like the majority of the answers indicate its bad practice to have multiple constructors. I don't entirely disagree with this, however, the situation arises as a result of trying to find a good solution to the mapping/conversion layer, which I asked in this question but never got a good answer to.
My code would look like this:
public class SomeController : Controller
{
private ISomeService _SomeService;
private IEntityConverter _EntityConverter;
// this would be used during unit tests when mocking the entity converter
public SomeController(ISomeService someService, IEntityConverter entityConverter)
{
_SomeService = someService;
_EntityConverter = entityConverter;
}
// this would be used when injecting via an IOC container, where it would be tedious
// to always specify the implementations for the converters
public SomeController(ISomeService someService)
: this(someService, new EntityConverter())
{
}
public ActionResult Index(SomeViewModel someViewModel)
{
if (!ModelState.IsValid)
return View(someViewModel);
else
{
ServiceInput serviceInput = _EntityConverter.ConvertToServiceInput(someViewModel);
_SomeService.DoSomething(serviceInput);
return View("Success");
}
}
}
In this very simple example, I am using an interface to do conversions between my view models and the entities that are inputs to the service layer.
I'd prefer to use an interface because this conversion can be mocked, rather than if a static method was used. However, I feel like it would be tedious to always have to specify, in the IOC container, what the implementations are for these conversion implementations, since the implementations for these conversion interfaces sit right next to the interfaces.
This may not be the best solution. I'm open to better alternatives.
Don't use multiple constructors. Your classes should have a single definition of what dependencies it needs. That definition lies in the constructor and it should therefore only have 1 public constructor.
I must say I'm not a fan of using mocking frameworks. I found that a good design of my application and my unit tests prevents me from having to use mocking frameworks all together (of course mileage may vary) .
One trick that helps me is allowing null references to be injected into the constructor by not validating the constructor arguments. This is very convenient for unit tests in cases where the class under test does not use the dependency, while in production you would still have the guarantee that null is not injected, since IOC containers will never inject null into a constructor (or at least none of the containers that I know).
Seems like a code-smell that you need an explicit constructor for testing. What if the testing ctor works but the production one doesn't? Seems like a door for bugs to creep in. It would be ideal for tests to use the same path as real clients as far as possible.
What is different between the two ?
Also if you're using some sort of attribute based DI (e.g. like MEF), I'd not be too worried about decoupling. Having an extra attribute (and the corresponding reference) should not be that big a hit... unless you foresee a change in IOC tech in the future.
Maybe I'm misreading your question, but I'm not sure why you would want to test different constructors. The tests should test what's actually going to be used.
For your tests, you ought to mock your dependencies so that they don't need an IoC container.
Using Moq:
Controller:
public SomeController(IService1 service1, IService2 service2)
{
// Do some cool stuff
}
Test Method:
[Test]
public void Some_Action_In_SomeController_Should_Do_Something()
{
var service1Mock = new Mock<IService1>();
var service2Mock = new Mock<IService2>();
var controller = new SomeController(service1Mock.Object, service2Mock.Object);
controller.Action();
// Assert stuff
}
It's all to do with your service locator, you need to configure it where you register your types.
Here is an example of using the default parameterless constructor when using Unity.
Note that by default the service locator will use the most specific constructor (the one with the most parameters)
ServiceLocator.Current.RegisterType<ICache, HttpContextCache>(new InjectionConstructor()); //use default constructor
So why did I need this? It is true I could have made a protected virtual method to resolve HttpContextBase and use extract and override in the test, or otherwise yet another interface with a method that creates the HttpContextBase that can be injected into this class.... or I could just tell unity to use the default constructor.
private readonly HttpContextBase _httpContextBase;
public HttpContextCache()
{
_httpContextBase = new HttpContextWrapper(HttpContext.Current);
}
public HttpContextCache(HttpContextBase httpContextBase)
{
_httpContextBase = httpContextBase;
}
This was a rare case and pretty much all other classes in the project have only one constructor
I've designed an application that uses the repository pattern, and then a separate service layer such as this:
public class RegistrationService: IRegistrationService
{
public void Register(User user)
{
IRepository<User> userRepository = new UserRepository();
// add user, etc
}
}
As you can see, I am instantiating my repository inside of the Register method. Now as I want to write some unit tests, I can't really get to it and replace it with a fake repository can I?
I don't want to add the repository as class variable though (and set it through a constructor) because I think that would make my code "smelly" (not all repositories are needed for all methods, and I don't need the calling layer to know about repositories etc.).
Suggestions?
You need to use Dependency Injection. UserRepository is a dependency of your RegistrationService class. To make your classes properly unit testable (i.e. in isolation of their dependencies), you need to "invert" what controls your dependency creation. Currently, you have direct control, and are creating them internally. Just invert that control, and allow something external (such as an IoC container like Castle Windsor) inject them:
public class RegistrationService: IRegistrationService
{
public RegistrationService(IRepository<User> userRepo)
{
m_userRepo = userRepo;
}
private IRepository<User> m_userRepo;
public void Register(User user)
{
// add user, etc with m_userRepo
}
}
I think I forgot to add. Once you allow your dependencies to be injected, you open up the possability of them being mockable. Since your RegistrationService now takes its dependent user repository as input to its constructor, you can create a mock repository and pass that in, instead of an actual repository.
Dependency Injection can come in really handy for these kinds of things:
public class RegistrationService: IRegistrationService
{
public void Register(User user)
{
this(user, new UserRepository());
}
public void Register(User user, IRepository<User> userRepository)
{
// add user, etc
}
}
This way you get the ability to use UserRepository as your default, and pass in a custom (Mock or Stub for testing) IRepository for whatever else you need. You may also want to change the scoping of the 2nd register method in case you don't want to expose it to everything.
An even better alternative would be to use an IoC container which would buy you syntax that is even more decoupled than the above example. You could get something like this:
public class RegistrationService: IRegistrationService
{
public void Register(User user)
{
this(user, IoC.Resolve<IRepository<User>>());
}
public void Register(User user, IRepository<User> userRepository)
{
// add user, etc
}
}
There are many IoC containers out there, as listed by other people's answers, or you could roll your own.
What you should be doing is using Inversion of Control or Dependency injection.
Your classes shouldn't be tied to an implementation of another class, particularly across layers like this, rather it should take the an interface representing a user repository as either a constructor, or as a property. Then when it runs, you supply the concrete implementation and it uses that. You can build fakes then that implement the repository interface and supply them at test time.
There are very many IOC containers, Unity, Ninject, Castle Windsor, and StructureMap to name a few.
I just wanted to be clear, during your unit tests, I don't know that you'd want to actually use the IOC Container. Integration tests, sure, but for the unit tests, just new up the object you are testing and provide your fake during that process. IOC containers are, at least IMO, there to help out at the application or integration testing levels, and make configuration there easier.
Your unit tests should probably stay 'pure' and just work with the objects you are trying to test. At least that's what works for me.
Just to add a bit of clarity (or perhaps not) to what everyone said, the way an IOC basically works is you tell it to replace X with Y. So what you would do is accept IRepository (as others have stated) as a param and then within the IOC you would tell it to replace IRepository with MockedRepository (for instance) for that specific class.
If you use an IoC that allows for web.config initialization, it makes transitioning from dev to prod very smooth. You simply modify the appropriate params within the config file and you are on your way - without needing to touch the code. Later, if you decide you want to move to a different data source - you just switch it out and you are on your way.
IoC is some fun-lovin stuff.
On a side note, you could do it without IOC injection as well if all you want to do is Unit Test. You could do this by overloading the constructor to accept an IRepository and just passing your mocked repo that way.
I'm working on something, well, almost verbatim at the moment. I'm using MOQ to mock up a proxy instance of my IUserDataRepository.
From the testing perspective:
//arrange
var mockrepository = new Mock<IUserDataRepository>();
// InsertUser method takes a MembershipUser and a string Role
mockrepository.Setup( repos => repos.InsertUser( It.IsAny<MembershipUser>(), It.IsAny<string>() ) ).AtMostOnce();
//act
var service = new UserService( mockrepository.Object );
var createResult = service.CreateUser( new MembershipUser(), "WebUser" );
//assert
Assert.AreEqual( MembershipCreateUserResult.Success, createResult );
mockrepository.VerifyAll();
MOQ can also be used to throw specific exceptions as well so that my UserService can be tested under those situations.
Then like as others have mentioned IoC will handle the required depenancies. In this case creating a real repository for the UserService class.
You could use an IOC container and then register a different repository.
My suggestion would still be to move the repository to a class parameter, and use an IoC container to inject the repository when needed. This way, the code is simple and testable.
I want to be better at using NUnit for testing the applications I write, but I often find that the unit tests I write have a direct link to the environment or underlying database on the development machine instead.
Let me make an example.
I'm writing a class which has the single responsibility of retriving a string, which has been stored in the registry by another application. The key is stored in HKCU\Software\CustomApplication\IniPath.
The Test I end up writing looks like this;
[Test]
public void GetIniDir()
{
RegistryReader r = new RegistryReader();
Assert.AreEqual(#"C:\Programfiles\CustomApplication\SomeDir", r.IniDir);
}
But the problem here is that the string #"C:\Programfiles\CustomApplication\SomeDir" is really just correct right now. Tomorrow it might have changed to #"C:\Anotherdir\SomeDir", and suddenly that breaks my unit tests, even though the code hasn't changed.
This problem is also seen when I create a class which does CRUD operations against a database. The data in the database can change all the time, and this in turn makes the tests fail. So even if my class does what it is intended to do it will fail because the database returns more customers that it had when I originally wrote the test.
[Test]
public void GetAllCustomersCount()
{
DAL d = new DAL();
Assert.AreEqual(249, d.GetCustomerCount());
}
Do you guys have any tips on writing Tests which do not rely on the surrounding environment as much?
The solution to this problem is well-known: mocking. Refactor your code to interfaces, then develop fake classes to implement those interfaces or mock them with a mocking framework, such as RhinoMocks, easyMock, Moq, et. al. Using fake or mock classes allow you to define what the interface returns for your test without having to actually interact with the external entity, such as a database.
For more info on mocking via SO, try this Google search: http://www.google.com/search?q=mock+site:stackoverflow.com. You may also be interesting in the definitions at: What's the difference between faking, mocking, and stubbing?
Additionally, good development practices, such as dependency injection (as #Patrik suggests), which allows the decoupling of your classes from its dependencies, and the avoidance of static objects, which makes unit testing harder, will facilitate your testing. Using TDD practices -- where the tests are developed first -- will help you to naturally develop applications that incorporate these design principles.
The easiest way is to make the dependencies explicit using dependency injection. For example, your first example has a dependency on the registry, make this dependency explicit by passing an IRegistry (an interface that you'll define) instance and then only use this passed in dependency to read from the registry. This way you can pass in an IRegistry-stub when testing that always return a known value, in production you instead use an implementation that actually reads from the registry.
public interface IRegistry
{
string GetCurrentUserValue(string key);
}
public class RegistryReader
{
public RegistryReader(IRegistry registry)
{
...
// make the dependency explicit in the constructor.
}
}
[TestFixture]
public class RegistryReaderTests
{
[Test]
public void Foo_test()
{
var stub = new StubRegistry();
stub.ReturnValue = "known value";
RegistryReader testedReader = new RegistryReader(stub);
// test here...
}
public class StubRegistry
: IRegistry
{
public string ReturnValue;
public string GetCurrentUserValue(string key)
{
return ReturnValue;
}
}
}
In this quick example i use manual stubbing, of course you could use any mocking framework for this.
Other way is to create separate database for tests.
You should read up on the inversion of control principle and how to use the dependency injection technique - that really helps you write testable code.
In your case, you should probably have an interface - e.g. IIniDirProvider - which is implemented by RegistryBasedIniDirProvider, which is resposible for providing the initial directory based off a specific key in the registry.
Then, when some other class needs to look up the initial directory, that other class should have the following ctor:
public SomeOtherClass(IIniDirProvider iniDirProvider)
{
this.iniDirProvider = iniDirProvider;
}
-allowing you to pass in a mock IIniDirProvider when you need to unit test SomeOtherClass. That way your unit test will not depend on anything being present in the registry.