In an MVC4 C# website, we are using Unit Testing to test our code. What we are currently doing is creating a mock database, then testing each layer:
Test the Database - connecting, initializing, load, etc.
Test the code accessing the database
Test the view layer
I want these three categories to be run in order and only if the previous one passed. Is this the right way to go about it? The old way we were doing it was using a Dependency Injection framework was a weird approach to mock testing. We actually created a mock class for each data accessor, which sucks because we have to re implement the logic of each method, and it didn't really add any value because if we made a mistake with the logic the first time, we'll make it a second.
I want these three categories to be run in order and only if the
previous one passed. Is this the right way to go about it?
No. You should be test everything in isolation and because of that any failing data access code should be completely unrelated to the view. So the view unit tests should fail for a completely different reason and because of that you should always run all tests.
In general, tests should run in isolation, and should not depend on any other tests. It seems to me that the view layer still depends on the data access code, but that you only abstracted the layer below. In that case, from the view's perspective, you are mocking an indirect dependency, which makes your unit tests more complex than strictly needed.
The old way we were doing it was using a Dependency Injection
framework was a weird approach to mock testing
I'm not sure if I get this, but it seems as if you were using the DI container inside your unit tests. This is a absolute no-no. Don't clutter your tests with any DI framework. And there's no need to. Just design your classes around the dependency injection principle (expose all dependencies as constructor arguments) and in your test you just manually new up the class under test with fake dependencies -or- when this leads to repetitive code, create a factory method in your test class that creates a new instance of the class under test.
We actually created a mock class for each data accessor, which sucks
I'm not sure, but it sounds as if there's something wrong with your design here. You would normally have a IRepository<T> interface for which you would have multiple implementations, such as a UserRepository : IRepository<User>, and OrderRepository : IRepository<Order>. In your test suite, you will have one generic FakeRespository<T> or InMemoryRepository<T> and you're done. No need to mock many classes here.
Here are two great books you should definitely read:
The Art of Unit Testing
Dependency Injection in .NET
Those books will change your life. And since you'll be reading anyway, do read this book as well (not related to your question, but code be a life changer as well).
Related
I'm trying to write unit tests for a class that instantiates other classes within it, but am struggling with how to instantiate those classes in a testable way. I'm aware of dependency injection, but this is somewhat different as the instantiation doesn't happen in the constructor.
This question really isn't specific to MVVM and C#, but that's what my example will use. Note that I've simplified this and it will not compile as-is - the goal is to show a pattern.
class ItemListViewModel
{
ItemListViewModel(IService service)
{
this.service.ItemAdded += this.OnItemAdded;
}
List<IItemViewModel> Items { get; }
OnItemAdded(IItemModel addedItem)
{
var viewModel = new ItemViewModel(addedItem);
this.Items.Add(viewModel);
}
}
class ItemViewModel : IItemViewModel
{
ItemViewModel(IItem) {}
}
As can be seen above, there is an event from the model layer. The ViewModel listens to that event and, in response, adds a new child ViewModel. This fits with standard Object Oriented programming practices that I'm aware of, as well as the MVVM pattern, and feels like quite a clean implementation to me.
The problem comes when I want to unit test this ViewModel. While I can easily mock out the service using dependency injection, I'm unable to mock out items added through the event. This leads to my primary question: is it OK to write my unit tests depending on the real version of ItemViewModel, rather than a mock?
My gut feel: that isn't OK because I'm now inherently testing more than ItemListViewModel, particularly if ItemListViewModel calls any methods on any of the items internally. I should have ItemListViewModel depend on mock IItemViewModels during testing.
There's a few tactics I've considered for how to do this:
Have ItemListViewModel's owning class listen to the event and add mocked out items. This just moves the problem around, though, as now the owning class can't be fully mocked out.
Pass an ItemViewModel factory into ItemListViewModel and use that instead of new. This would definitely work for mocking as it moves things to be based on dependency injection...but does that mean I need a factory for every class I ever want to mock in my app? This feels wrong, and would be a pain to maintain.
Refactor my model and how it communicates with the ViewModel. Perhaps the eventing pattern I'm using isn't good for testing; though I don't see how I would get around needing to ultimately construct an ItemViewModel somewhere in code that needs to be tested.
Additionally, I've searched online and looked through the book Clean Code, but this really hasn't been covered. Everything talks about dependency injection, which doesn't clearly solve this.
is it OK to write my unit tests depending on the real version of
ItemViewModel, rather than a mock?
Yes!
You should use real implementation as long as tests become slow or very very complicated to setup.
Notice that tests should be isolated, but isolated from other tests not from other dependencies of unit under the test.
Main issue of the testing is that applications using shared state (database, filesystem). Shared state makes our tests dependent on each other (tests for adding and removing items can not be run in parallel). By introducing mocking we eliminate shared state between tests.
Sometimes application being divided into independent domain modules, which "communicate" with each other via abstracted interface. To keep modules independent we will mock communication interface, so module under the test will not depend on implementation details of another domain module.
Mocking literally all dependencies will make maintenance/refactoring changes a nightmare, because every time you going to extract some logic into dedicated class you will be forced to change/rewrite test suit of the unit you are refactoring.
Your scenario is good example, by not mocking creating of ItemViewModel, you will be able to introduce a factory inject it into the class under the test and run already existing test suit to make sure that factory didn't introduce any regressions.
While I can easily mock out the service using dependency injection, I'm unable to mock out items added through the event.
Misko Hevery wrote about this pattern: How to Think About the New Operator
If you mix application logic with graph construction (the new operator) unit-testing becomes impossible for anything but the leaf nodes in your application.
So if we were to look at your problem code:
OnItemAdded(IItemModel addedItem)
{
var viewModel = new ItemViewModel(addedItem);
this.Items.Add(viewModel);
}
then one change we could consider is replacing this direct call to ItemViewModel::new with a more indirect approach
var viewModel = factory.itemViewModel(addedItem);
Where factory provides a capability to create ItemViewModel, and the design allows us to provide substitutes.
ItemListViewModel(IService service, Factory factory)
{
this.service.ItemAdded += this.OnItemAdded;
this.factory = factory;
}
Having done that, you can (when appropriate) use a Factory that provides some simpler implementation of your item view model.
When is this important? One thing to notice is that you are asking about ItemViewModel, but you aren't asking about List. Why is that?
A couple of answers: List is stable; we aren't at all worried that the behavior of List itself is going to change in a way that causes an observable change to the behavior of ItemListViewModel. If the test reports a problem later, there isn't going to be any doubt that we introduced a mistake in our code.
Also, this.List is (presumably) isolated. We don't have to worry that our test results are going to be flaky because some other code is running at the same time. In other words, are test is not vulnerable to problems caused by shared mutable state.
If those properties also hold for ItemViewModel, then adding a bunch of ceremony to your code to create separation between these two implementations isn't actually going to make your design any "better".
Sorry if I am asking very basic question,
I have set of web services (developed using .Net WebApi). These services are either business layer or data access layer APIs. These APIs are either dependent on other services or database itself.
I want to write unit test cases for it. I have following questions
As business layer APIs has dependency on data access service or some other service. If I write unit test just to invoke business API then it would invoke data access API. Is this the correct way to write unit test case? or should I inject all dependency object with unit test? I think earlier one would be integration test not unit test.
Should I write unit tests for Data access layer at all? I checked this link (Writing tests for data access code: Unit tests are waste) and it says DAL does not require unit tests. Should I still write tests for data access layer. I think it would be integration test not unit tests?
Question 1:
I would say if you want to do TDD, then it's not the "correct" way, because as you said, you would be performing integration tests. Then again, maybe you don't want to do TDD and integration tests are good enough for you, but to answer the question: this wouldn't be the proper way to **unit-**test your code.
Question 2
I would say it depends what you have in your data access layer. For instance, if you implement repositories, you will probably want to write a few tests.
Save method
You want to make sure that given an entity that you have retrieved from your repository, editing some properties of this entity and persisting the changes will actually save the modifications and not create a new entity. Now: you might think this is an integration test, but it really depends on how well designed your code is. For instance, your repository could be just an extra layer of logic on top of a low-level ORM. In that case, when testing the save method, what you will do is that you will assert that the right methods are called with the right parameters on the ORM service injected in your repository.
Errors and exceptions
While accessing data, it is possible to have problems such as connection to the database being broken, or that the format of the data is not as expected, or deserialization problems. If you want to provide some good error handling and perhaps create custom exceptions and add more information to them depending on the context, then you definitely want to write tests to make sure the corrext information is propagated
on the other hand
If your DAL is just a few classes that wrap a non-mockable ORM, and you don't have any logic in there, then perhaps you don't need tests, but it seems that this doesn't happen too often, you will pretty much always have a bit of logic that can go wrong and that you want to test.
I am trying to following TDD and I have come across a small issue. I wrote a Test to insert a new user into a database. The Insert new user is called on the MyService class, so I went ahead and created mytest. It failed and I started to implement my CreateUser method on my MyService Class.
The problem I am coming across is the MyService will call to a repository (another class) to do the database insertion.
So I figured I would use a mocking framework to mock out this Repository class, but is this the correct way to go?
This would mean I would have to change my test to actually create a mock for my User Repository. But is this recommended? I wrote my test initially and made it fail and now I realize I need a repository and need to mock it out, so I am having to change my test to cater for the mocked object. Smells a bit?
I would love some feedback here.
If this is the way to go then when would I create the actual User Repository? Would this need its own test?
Or should I just forget about mocking anything? But then this would be classed as an integration test rather than a unit test, as I would be testing the MyService and User Repository together as one unit.
I a little lost; I want to start out the correct way.
So I figured I would use a mocking framework to mock out this
Repository class, but is this the correct way to go?
Yes, this is a completely correct way to go, because you should test your classes in isolation. I.e. by mocking all dependencies. Otherwise you can't tell whether your class fails or some of its dependencies.
I wrote my test initially and made it fail and now I realize I need a
repository and need to mock it out, so I am having to change my test
to cater for the mocked object. Smells a bit?
Extracting classes, reorganizing methods, etc is a refactoring. And tests are here to help you with refactoring, to remove fear of change. It's completely normal to change your tests if implementation changes. I believe you didn't think that you could create perfect code from your first try and never change it again?
If this is the way to go then when would I create the actual User
Repository? Would this need its own test?
You will create a real repository in your application. And you can write tests for this repository (i.e. check if it correctly calls the underlying data access provider, which should be mocked). But such tests usually are very time-consuming and brittle. So, it's better to write some acceptance tests, which exercise the whole application with real repositories.
Or should I just forget about mocking anything?
Just the opposite - you should use mocks to test classes in isolation. If mocking requires lots of work (data access, ui) then don't mock such resources and use real objects in integration or acceptance tests.
You would most certainly mock out the dependency to the database, and then assert on your service calling the expected method on your mock. I commend you for trying to follow best practices, and encourage you to stay on this path.
As you have now realized, as you go along you will start adding new dependencies to the classes you write.
I would strongly advise you to satisfy these dependencies externally, as in create an interface IUserRepository, so you can mock it out, and pass an IUserRepository into the constructor of your service.
You would then store this in an instance variable and call the methods (i.e. _userRepository.StoreUser(user)) you need on it.
The advantage of that is, that it is very easy to satisfy these dependencies from your test classes, and that you can worry about instantiating of your objects, and your lifecycle management as a separate concern.
tl;dr: create a mock!
I have two set of testing libraries. One for UnitTests where I mock stuff. I only test units there. So if I would have a method of AddUser in the service I would create all the mocks I need to be able to test the code in that specific method.
This gives me a possibility to test some code paths that I would not be able to verify otherwise.
Another test library is for Integration tests or functional tests or whatever you want to call it. This one is making sure that a specific use case. E.g. Creating a tag from the webpage will do what i expect it to do. For this I use the sql server that shipps with Visual studio 2012 and after every test I delete the database and start over.
In my case I would say that the integration tests are much more important then the unit tests. This is because my application does not have so much logic, instead it is displaying data from the database in different ways.
Your initial test was incomplete, that's all. The final test is always going to have to deal with the fact the new user gets persisted.
TDD does not prescribe the kind of test you should create. You have to choose beforehand if it's going to be a unit test or some kind of integration test. If it's a unit test, then the use of mocking is practically inevitable (except when the tested unit has no dependencies to isolate from). If it's an integration test, then actual database access (in this case) would have to be taken into account in the test.
Either kind of test is correct. Common wisdom is that a larger unit test suite is created, testing units in isolation, while a separate but smaller test suite exercises whole use case scenarios.
Summary
I am a huge fan of Eiffel, but while the tools of Eiffel like Design-by-Contract can help significantly with the Mock-or-not-to-Mock question, the answer to the question has a huge management-decision component to it.
Detail
So—this is me thinking out loud as I ponder a common question. When contemplating TDD, there is a lot of twisting and turning on the matter of mock objects.
To Mock or Not to Mock
Is that the only binary question? Is it not more nuanced than that? Can mocks be approached with a strategy?
If your routine call on an object under test needs only base-types (i.e. STRING, BOOLEAN, REAL, INTEGER, etcetera) then you don't need a mock object anyhow. So, don't be worried.
If your routine call on an object under test either has arguments or attributes that require mock objects to be created before testing can begin then—that is where the trouble begins, right?
What sources do we have for constructing mocks?
Simple creation with:
make or default create
make with hand-coded base-type arguments
Complex creation with:
make with database-supplied arguments
make with other mock objects (start this process again)
Object factories
Production code based factories
Test code based factories
Data-repo based data (vs hand-coded)
Gleaned
Objects from prior bugs/errors
THE CHALLENGE:
Keeping the non-production test-code bloat to a bare minimum. I think this means asking hard but relevant questions before willy-nilly code writing begins.
Our optimal goal is:
No mocks needed. Strive for this above all.
Simple mock creation with no arguments.
Simple mock creation with base-type arguments.
Simple mock creation with DB-repo sourced base-type arguments.
Complex mock creation using production code object factories.
Complex mock creation using test-code object factories.
Objects with captured states from prior bugs/errors.
Each of these presents a challenge. As stated—one of the primary goals is to always keep the test code as small as possible and reuse production code as much as possible.
Moreover—perhaps there is a good rule of thumb: Do not write a test when you can write a contract. You might be able to side-step the need to write a mock if you just write good solid contract coverage!
EXAMPLE:
At the following link you will find both an object class and a related test class:
Class: https://github.com/ljr1981/stack_overflow_answers/blob/main/src/so_17302338/so_17302338.e
Test: https://github.com/ljr1981/stack_overflow_answers/blob/main/testing/so_17302338/so_17302338_test_set.e
If you start by looking at the test code, the first thing to note is how simple the tests are. All I am really doing is spinning up an instance of the class as an object. There are no "test assertions" because all of the "testing" is handled by DbC contracts in the class code. Pay special attention to the class invariant. The class invariant is either impossible with common TDD facilities, or nearly impossible. This includes the "implies" Boolean keyword as well.
Now—look at the class code. Notice first that Eiffel has the capacity to define multiple creation procedures (i.e. "init") without the need for a traffic-cop switch or pattern-recognition on creation arguments. The names of the creation procedures tell the appropriate story of what each creation procedure does.
Each creation procedure also contains its own preconditions and post-conditions to help cement code-correctness without resorting to "writing-the-bloody-test-first" nonsense.
Conclusion
Mock code that is test-code and not production-code is what will get you into trouble if you get too much of it. The facility of Design-by-Contract allows you to greatly minimize the need for mocks and test code. Yes—in Eiffel you will still write test code, but because of how the language-spec, compiler, IDE, and test facilities work, you will end up writing less of it—if you use it thoughtfully and with some smarts!
I've got NHibernate-based (constructor ISessionFactory injection) generic repository implementation which is stored inside DAL. It implements contract which is stored in `Domain Layer'.
Should I test real repository behavior using SQl CE or should I refactor my application to support agnostic-like (like in Tim Maccharty's book http://www.wrox.com/WileyCDA/WroxTitle/productCd-0470147563,descCd-authorInfo.html) Unit of Work and then give my fake implementation of IUnitOfWorkRepository?
Is it a valid approach to run tests on a local database exposing real repository implementation?
Thanks!
The issue is what your are testing and why. That will answer the question.
If:
I want to test a third party tool
That is, are you testing if NHibernate is working (not a kind of test
I do). Then do whatever it requires, so refactoring not required. Loose yourself.
I want to test how my code interacts with a thrid party tool
Then you are talking about what I like to call a interaction test. Refactoring is required as your more interested in how your using NHiberate than if it works.
I want to test my code
The abstract NHibernate entirely. Do whatever is necessary ... wrapper? Your now back into unit testing.
I want to test my application from a user point of view
I think this is above the scope your talking. But you can use this scope talking about components. So ... hmmm ... worthwhile but not easy. Not a unit test, so you want to instantiate the component/app and run the whole thing as its 'user' does. I call these 'UATs' and usually implement as 'Coded UATs'.
A unit test is testing a unit in isolation. So, no, it's not even a unit test if you're going to the database.
Abstract away and test your repositories with mocked up interfaces.
I think to test the repositories you need to use the actual scenario. Otherwise you don't have any other place to test the database access. Mocking the repositories is not a good practice. Because you don't have any logic which is need to test in the repositories. I think you need to write integration tests which is calling actual repositories to have any benefit from it.
My question may appear really stupid for some of you but i have to ask.. Sorry..
I don't really understand principles of unit testing.. How can you test classes of your business classes or Data access layer without modify your database?
I explain, i have a functionality who update a field in a database.. Nothing so amazing..
The Business layer class is instantiated and the method BLL.Update() makes some controls and finally instantiate a DAL class who launch a stored procedure in the database with the correct parameters.
Its works but my question is..
To do unit tests who test the DALayer class i have to impact the database in the tests! To test for example if the value 5 is well passed to the DataBase i have to do that and database's field will be 5 after the test!
So i know normally the system is not impacted by tests so i don't understand how you can do tests without without execute methods..
Tx for answers and excuse my poor English..
I will divide your question into several sub questions because it is hard to answer them together.
Unit testing x Integration testing
When you write unit test you are testing simple unit. That means you are testing single execution path in tested method. You need to avoid testing its dependencies like mentioned database. You usually write simple unit test for each execution path so that you have good code coverage by your tests.
When you write integration test you are testing all layers to see if integration and configuration works. You usually don't write integration test for each execution path because there is to many combination accross all layers.
Testing business classes - unit testing
You need to test your business classes without dependency to DAL and DB. To do that you have to design your BL class so that those dependencies are injected from outside. First you need to define abstract class or interface for DAL and pass that DAL interface as parameter to constructor (another way is to expose setable property on BL class). When you test your BL class you will use another implementation of DAL interface which is not dependent on DB. There are well known test patterns Mock, Stub and Fake which defines how to create and use those dummy implementations. Mocking is also supported by many testing frameworks.
Testing data access layer - integration testing
You need to test your DAL against real DB. You will prepare testing DB with test set of data and you will write your tests to work with that data. Each test will run in its own transaction which will be rolled back at the end so it will not modify initial data set.
Best regards, Ladislav
For the scenario you describe in terms of db interaction, mocking is useful. If you have a chance, take a look at Rhino Mocks
You use Inversion of Control together with a mocking framework, e.g. Rhino Mocks as someone already mentioned
If you are not resorting to mocking and using actual DB in testing then it will be integration testing in layman terms and it's not a unit test anymore. I worked on a project where a dedicated sql .mdf was in source control that was attached to database server using NUnit in [Setup] part of [SetupFixture], similary detached in [TearDown]. This was done everytime NUnit test were performed and could be very time consuming depending upon the SQL code you have as well as size of data can make worse.
Now the catch is the maintenance overhead, you may change the DB scehma during you sprint cycle and at relaease, the change DB script has to be run on all databases used in your development and testing including the one used for integration testing as mentioned above. Not just that, new test data (as someone mentioned above) has to be popoulated for new tables/columns created and likewise, the exisitng data may need to be cleansed as well owing to requirements changes or bug fixes.
This seems to be a task in itself and someone competent in team can take the ownership or if time permits you can integrate the execution of change scripts as part of Continuous Integration if you already implemented one. Still the adding and cleansing the test data need to be taken care of manually.