TL;DR - I mixed up "Integration Tests" with "Unit Tests".
I'm confused about Unit Testing and IoC containers... :(
I've read this article about how you should not use IoC containers in Unit Testing. This seems to be an opinion of many people on SO and in various other articles. In Unit Tests, you test your methods but any dependencies should be mocked.
Using the aforementioned article, I'd like to ask some questions.
To put it another way, if component A calls component B then from a unit testing perspective, we cannot let component A call the actual implementation of component B. Instead, component B must be mocked.
But... why?
We use a fake instead of the real component B so that 1) our tests do
not rely on code in any other class, 2) component B returns the same
data every time and 3) we can intercept calls to component B so we can
check how and when it is being called.
ad. 1) Instead of testing, what would happen in the real application, I'm now reasonlessly falsificating component B....to what end? So that I know that component A is tested in isolated manner? But my application uses both components together and these components work together.
The citation implies that I have to Unit Test component A and component B in isolation and that I should test only the business of the component.
But that undermines the whole point of automated testing in which I create assurances about the functions of the application, that the application will not crash, using these two components together. Not about its internal units in isolated context.
ad. 2) I know that everything I test is deterministic and for various inputs X it will return some Y, or throw an exception or something else - that's what I'm actually testing.
ad. 3) I can imagine this makes sense in complex tests...
To me mocking makes sense if component B is a 3rd party code I cannot easily create in a testing class without duplicating an awful lot of a code...Or if I have reasons not to call the actual implementation of component B such as not really wanting to do actual changes in database, not actually sending emails, not actually moving/writing/reading/deleting files etc.
But then, I'd mock using a different IoC container, where instead of Bind<ISomeService>().To<BusinessImplementation>() I would write Bind<ISomeService>().To<TestImplementation() (code example in Ninject)
By testing, I want to make assurances about the application, what would happen in deployed application and by mocking dependencies without good reason, I test in a very different context.
When the application starts, it uses the IoC container as I wrote it. The dependencies of the application are resolved using the IoC container.
I believe I'm probably wrong about something but I can't see it yet...
The purpose isn't to replace integration tests that will test modules from a higher level. Unit tests are intended to test a discrete class in isolation, mostly to confirm that the design and coding of that class is complete.
Instead, component B must be mocked. But... why?
Simply put, Unit Testing is for testing a unitary piece of feature. If the test fails, will it be because of component A or component B?
What the test is about?
Does component B pass its own battery of tests?
Testing component A along with a real instance of B will not answer these questions. On the contrary, it will rise up more questions than it can actually answer.
Instead of testing, what would happen in the real application, I'm now reasonlessly falsificating component B....to what end?
Actually, it is to isolate component A from component B so that any misbehave is only caused by component A. This it to reduce complexity around testing and to make it clear what you are doing, hence the "unit" in unit testing.
To me mocking makes sense if component B is a 3rd party code I cannot easily create in a testing class without duplicating an awful lot of a code...
Basically, you can do it this way. And this is not only what matters in unit testing. Instead, using dependency injection, one shall mock every reference types so that one isolates component A from any external influence, that is to make sure that component A behaves according to the expectations.
The day you want to test component A with a real instance of component B is actually not the day you are doing unit testing, but this is called integration testing, and those tests shall be written after you are sure that every component behaves in its unitary form.
Please see the answers of this question: Unit Testing or Functional Testing?
On a side note, it is not recommended to use DI containers in unit testing. It complexes the tests for no added value.
Related
I have a class called Customer and I wish to unit test this class and its public interface. To be able to unit test, I have to test Customer in isolation from its real dependencies. Other than Customer, I have a Monster class that I have created.
My application is using a game framework that defines a Shape (represents a shape) and Vec2F (represents a vector used for math). Customer relies(uses) on Shape and Vec2F. It also uses a Monster.
Now I have to mock these real dependencies for my tests to be unit tests and not integration tests. However, what defines "real" dependencies? Like I would understand why I would mock my own implementation of Monster but Vec2F and Shape from the framework I use seem to be such fundamental structures.
Tests should be isolated from other tests. For this you need to mock any global state consumed by the system under the test.
If system under the test doesn't use global/shared state - mock nothing.
In perfect world, where setup new database will take a milliseconds, you can create new database for every test (In-Memory database in EF Core).
But in our real world we have dependencies which represents global state or if not, still will make tests slow(web services, file system, any external resources).
Those dependencies you wanna mock to provide quicker feedback(unit tests).
You can have very complicated dependencies hierarchy, which don't use global state or external resources, but configuring a test case with those dependencies, will become very very complex and difficult.
In this case you will introduce an abstraction around very very complex dependency and will mock it in the consumer's tests.
In your particular test case, I would mock nothing, unless framework classes depend on the drawing screen logic(depend on environment API).
Since testing software is a huge task, you split it into several tasks to make it manageable. In unit-testing your focus is on finding bugs that can be found by looking at small software pieces in isolation. That is, unit-testing aims at finding a special kind of bugs. Integration testing, for example, aims at a different kind of bugs, which can not be found by unit-testing.
Focusing on finding the bugs in an isolated piece of software does not mean you really must isolate that piece of software technically by mocking the dependencies. Nowadays mocking frameworks make mocking fairly easy (the level of difficulty varies among programming languages, though). Still, mocking is always some extra effort and also comes with disadvantages. For example, tests that use mocking are more closely linked to the code's implementation and thus are more likely to need maintainenance if implementation details change.
Therefore, mocking should only be done if there is a good reason to mock. Good reasons are:
You can not easily make the depended-on-component (DOC) behave as intended for your tests.
Does calling the DOC cause any non-derministic behaviour (date/time, randomness, network connections)?
The test setup is overly complex and/or maintenance intensive (like, need for external files)
The original DOC brings portability problems for your test code.
Does using the original DOC cause unnacceptably long build / execution times?
Has the DOC stability (maturity) issues that make the tests unreliable, or, worse, is the DOC not even available yet?
For example, you (typically) don't mock standard library math functions like sin or cos, because they don't have any of the abovementioned problems. The same could hold, in your case for Vec2F and Shape, but you would have to judge that by yourself. The above list of criteria should help you there.
It sounds like the Customer is a domain level type. In this case, you should invert the dependency to Shape and Vec2F (this looks like the view-layer implementation) since the framework is a detail and it is on a lower level than the Customer is.
I’ve seen lots of info on this topic but wanted to provide a specific example and ask some specific questions.
I’m currently in the middle of a development project in which I’m programming against a telephony system via the OEM provided SDK. I’ve created several interfaces & classes that extend the functionality of the SDK and have refactored these to support dependency injection for ease of testing. At the lowest level, I have methods like “retrieveUserInfo” that accepts a connection interface and a query object.
When Unit testing, I could actually create a connection to the telephony system, get back a given user, and check it for the correct data. This test is meaningful to me as it lets me know both my Middleware and the underlying OEM libraries are working correctly; however, because it’s actually creating a connection to an outside system, it seems more like an integration test to me (the test will fail if you can’t connect to the telephony system, a user is not configured as expected, I have some bug in my business logic, or there is an issue with the underlying libraries).
Should this test be labeled as an integration test? If so, how would I go about attempting to unit test methods like “retrieveUserInfo”? How do I properly segment these 2 types of tests?
Defining what a 'unit' is, is quite difficult. But if what you're testing is putting calls on external libraries that actually call to different systems, then you're definitely in the realm of integration testing.
What a unit is limited to is a bit subjective, but might be restricted to a class or public method on a class.
If you want to unit test a method that calls methods on an external dependency, then that's something you want to mock or stub (see Moq for a good mocking library).
I am having difficulties while trying to understand the purpose of mocking my WCF applications in unit tests. I have read this article Testing with mock objects and I believe I got the idea why we use mocking in standard application - it is better to test behaviour rather than implementation of the method. So with using Mock objects, I can test whether certain method called certain mock object, whether it changed some properties etc.
But while I was searching for some good ways how to test WCF, everyone was suggesting to use Mocking as well. The thing is, that I feel like I should test whether method (which is communication with service) is really able to reach the service and obtain result, that is satisfactory...which is not the case I will achieve using mock object.
Question:
Is using mock objects in my WCF app unit tests really intended to test only whether the method tried to call the OperationContract(method) exposed by service (while not expecting the real results)?
Or am I missing something?
The purpose of Unit Testing is not to test your application, but to make sure the code you've written is doing what is intended and subsequently let you know when you've made a simple coding goof. When it comes to testing for communication-based services, there are a dozen other factors, not the least of which being actual connectivity, that could affect your connection but not actually tell you anything useful about your code. Thus, you should rely on running debug runs of your application to test end-to-end functionality, and Unit Tests with those mocks to test the actual code functionality.
Will you miss something here and there? Yes, but the definition of good Unit Tests is such that you'll eventually have to touch them up when this happens.
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).
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.