Integration or unit testing? Testing classes without access to external systems - java

Integration tests depends on external systems such as database or network connection. These components should be mock in unit testig.
But when we testing three different classes which behavior depends on each other is this an integretion or unit test? Should that classes be mocked? Lets assume that these classes have no acces to external systems and their behavior is strictly connected.

First of all, the terminology varies from company to company.
According to the book "How Google Tests Software" they call tests "Small Tests", "Medium Tests" and "Large Tests", if I remember correctly.
Other companies call it "Whitebox Tests", "Unit Tests", "Integration Tests", "End-to-End Tests". Even though the same name might be used in one company, it could mean something different in another company.
Secondly:
To mock or not to mock depends on what you want to test. If you want to test the interaction of those 3 classes then I suggest using all three as is, unless: If you want to isolate the behaviour of one class or desire a hard-to-achieve-behaviour/unrealistic behaviour/not-yet-implemented-behaviour or it is hard to use the other classes, I suggest mocking the other classes.

As I know.
Purposes of both testing are different from each other.
https://ocw.mit.edu/courses/aeronautics-and-astronautics/16-842-fundamentals-of-systems-engineering-fall-2015/lecture-notes/MIT16_842F15_Ses9_Ver.pdf
But unit testing may support integration testing; If used unit testing framework supports.

Related

How to measure a unittest vs. intergrationtest? [duplicate]

This question already has answers here:
What's the difference between unit, functional, acceptance, and integration tests? [closed]
(8 answers)
Closed 2 years ago.
I work on my thesis and it's about softwaretesting. The programming language is Java.
I have a huge program with over 450.000 lines of code (without comments and blankspaces). There are also many JUnit-tests.
My question right now is: How can I get to know if a test is a unittest or an intergrationtest?
My ideas: Can I use the execution time of the tests? Or can I measure the performance of the CPU?
Do you have any tips? Do you have more experience in softwaretesting? I am not new to this, but this case is a bit new and huge for me...
Thank you in advance! :)
Alexis described the difference between unit and integration tests completely above, but I felt the need to chime in on the particularities of java and how to write and notice the difference between unit and integration tests.
Unit Tests
Generally for unit tests, a mocking framework is used to mock certain dependencies of a particular class and of a particular method. Since with unit tests, we only want to test a single unit of the code (class methods) we don't want to have to worry about the other classes that method communicates with, so we mock those external dependencies and often verify that the method call to those external dependencies was carried out, without actually running the external method.
Mocking is a powerful tool to write strong tests for your application and it encourages developers to write clean, well-designed and loosely-coupled code.
A common example you will see throughout a java project is the Mockito Framework. I advise reading more on the topic here.
Integration Tests
"Testing performed to expose defects in the interfaces and in the interactions between integrated components or systems."
In java terms, this often refers to the interaction between classes. How class A calls class B and ensuring the link between them works correctly in regard to data transmission, error handling and control flow. Integration tests don't typically use a mocking framework but in-practice they can. Generally you want to fully test the component interactions without mocking out the dependency link. However, this depends on your needs in regard to application design. More information on this can be found here
Typically with integration tests, the database is tested regarding the CRUD (Create-Read-Update-Delete) operations to it. Unit tests have no connection to a database. This is because tests requiring a database connection will have side effects by their very nature. There is leakage from the concept of testing a "single unit" of your code. Therefore, normally the database is tested from integration tests and up.
Requiring this database connection will often cause your integration tests to run dramatically slower than your unit tests. This is due to needing to roll up the database for each set of transactions for a test class and often if you're using an IOC container (like Spring) then further overhead to time will exist. Typically, for integration tests we use a test database, rather than the real database, and is often in-memory.
In summary
If your project is designed well, the unit tests and integration tests should be segregated by package. It makes sense conceptually, and architecturally it is a better approach for developers to adapt to and feel comfortable with. It also completely draws that line between what is an integration test and what is a unit test.
Unit tests are very fast and should be the foundation of your application test suite.
Integration tests can be slow in most cases due to requiring a database connection but can cover more variants than a unit test can.
Unit tests typically use a mocking framework to mock external dependencies.
Integration tests typically use the real dependency objects for testing.
Unit tests should not have a database connection.
Integration tests typically do have a connection to a test database.
There are tons of articles/books about this and with a single query in Google you will find more, but in short:
Unit tests are the tests that test only the smallest unit (in Java the smallest unit is a method) in isolation.
Integration tests test the communication/collaboration between dependent units (in Java you might test that certain classes communicate properly).
There is no specific hint or annotation that declare your tests as Units Tests or Integration Tests, you have to dive on the test and figure it out.
You can measure the execution time of the tests really easily. There are a lot of tools for that but the Intellij (which is the most common IDE for Java) has a built-in feature for that. In the picture, you can see the execution time of the test suite printed by this IDE.

What are integration tests containing and how to set them up

I’m currently learning about unit tests and integration testing and as I understood it, unit tests are used to test the logic of a specific class and integration tests are used to check the cooperation of multiple classes and libraries.
But is it only used to test multiple classes and if they work together as expected, or is it also valid to access databases in an integration test? If so, what if the connection can‘t be established because of a server sided error, wouldn’t the tests fail, although the code itself would work as expected? How do I know what‘s valid to use in this kind of tests?
Second thing I don‘t understand is how they are set up. Unit tests seem to me have a quite common form, like:
public class classTest {
#BeforeEach
public void setUp(){
}
#Test
public void testCase(){
}
}
But how are integration tests written? Is it commonly done the same way, just including more classes and external factors or is there another way that is used for that?
[... ] is it also valid to access databases in an integration test? [...] How do I know what‘s valid to use in this kind of tests?
The distinction between unit-tests and integration tests is not whether or not more than one component is involved: Even in unit-testing you can get along without mocking all your dependencies if these dependencies don't keep you from reaching your unit-testing goals (see https://stackoverflow.com/a/55583329/5747415).
What distinguishes unit-testing and integration testing is the goal of the test. As you wrote, in unit-testing your focus is on finding bugs in the logic of a function, method or class. In integration testing the goal is then, obviously, to detect bugs that could not be found during unit-testing but can be found in the integrated (sub-)system. Always keeping the test goals in mind helps to create better tests and to avoid unnecessary redundancy between integration tests and unit-tests.
One flavor of integration testing is interaction testing: Here, the goal is to find bugs in the interaction between two or more components. (Additional components can be mocked, or not - again this depends on whether the additional components keep you from reaching your testing goals.) Typical questions in the interactions of two components A and B could be, for example if B is a library: Is component A calling the right function of component B, is component B in a proper state to be accessed by A via that function (B might not be initialized yet), is A passing the arguments in the correct order, do the arguments contain the values in the expected form, does B give back the results in the expected way and in the expected format?
Another flavor of integration testing is subsystem testing, where you do not focus on the interactions between components, but look at the boundaries of the subsystem formed by the integrated components. And, again, the goal is to find bugs that could not be found by the previous tests (i.e. unit-tests and interaction tests). For example, are the components integrated in the correct versions, can the desired use-cases be exercised on the integrated subsystem etc.
While unit-tests form the bottom of the test pyramid, integration testing is a concept that applies on different levels of integration and can even focus on interfaces orthogonal to the software integration strategy (for example when doing interaction testing of a driver and its corresponding hardware device).
Second thing I don‘t understand is how they are set up. [...] how are integration tests written?
There is an extreme variation here. For many integration tests you can just use the same testing framework that is used for unit-tests: There is nothing unit-test specific in these frameworks. You will, certainly, in the test cases have to ensure that the setup actually combines the components of interest in their proper versions. And, whether or not additional dependencies are just used or mocked needs to be decided (see above).
Another typical scenario is to perform integration tests in the fully integrated system, using a system-test-like setup. This is often done out of convenience, just to avoid the trouble to create different special setups for the different integration tests: The fully integrated system just has them all combined. Certainly, this has also disadvantages, because it is often impossible or at least impractical to perform all integration tests as desired this way. And, when doing integration testing this way the boundaries between integration testing and system testing get fuzzy. Keeping focused in such a case means you really have to have a good understanding of the different test goals.
There are also mixed forms, but there are too many to describe them here. Just one example, there is a possibility to mock some shared libraries with the help of LD_PRELOAD (What is the LD_PRELOAD trick?).
It would be valid to access a database as part of an integration test, as integration tests are supposed to show whether a feature is working correctly.
If a feature were to not work because of a failed connection to a server side error, you would want the test to fail to inform you that this feature is not working. Integration tests are not there to inform you where the fault lies, just that a feature is not working.
See https://stackoverflow.com/a/7876055/10461045 as this helps to clarify the widely accepted difference.
Using a database (or an external connection to a service you are using) in an integration test is not only valid, but should be done. However, do not rely on integration tests heavily. Unit test every logic element you have and set up integration tests for certain flows.
Integration tests can be written in the same way, except (as you mentioned) they include more methods etc. In fact, the code snippet you've shown above is a common start write-up of an integration test.
You can read up more on tests here: https://softwareengineering.stackexchange.com/questions/301479/are-database-integration-tests-bad

UnitTesting Fundamentals - What exactly to test? [duplicate]

This question already has answers here:
What is the difference between integration and unit tests?
(21 answers)
Closed 7 years ago.
I know that Unit Testing is all about testing individual units of code and mocking the other dependencies like database connections, file I/O etc.
I have a few questions on unit tests
what is that "UNIT" in unit testing that we need to test? Is it a method of a class? or a use-case? Because use-case testing seems more of an integration test to me.
Mocking external dependencies. Does it mean to mock all references to any external class even if it is same package?
The 'Unit' in unit testing is not well defined.
However it is often used to refer to the process of testing an individual function or method. Unit tests like these are often combined into a group which tests a group of related functions or methods (e.g. a class).
As you suspect, the unit under test should be isolated from any other code during testing. This allows you to be sure that any error occurs within the code you wish to test.
For a much better and more detailed explanation, I recommend Martin Fowler's post on the issue of Unit Testing, which directly addresses this issue:
Unit testing is often talked about in software development, and is a term that I've been familiar with during my whole time writing programs. Like most software development terminology, however, it's very ill-defined, and I see confusion can often occur when people think that it's more tightly defined than it actually is.
what is that "UNIT" in unit testing that we need to test? Is it a method of a class? or a use-case?
A chip is a unit to a RAM. Ram is a Unit to Motherboard and motherboard can be a unit in a border context. So there is no specific answer for your question. But mostly we use methods as units because they are the smallest elements that we can test.
Sometimes even a class or a bigger component can be a unit. It depends on your context and how important and complex that particular "unit" is?
Mocking external dependencies. Does it mean to mock all references to any external class even if it is same package?
You mock if you do not have direct access to some component. (class...etc) It doesn't matter where it is. If you want to test something which depends on something that hasn't been implemented yet, you need to mock. What should mock is depend on what you want to test!
(ex. I want to implement a Tsunami alert system but the hardware (which send the wave signal) which should be in the sea is not implemented yet. So if I want to test the alert system I built I may be need to mock the behavior of that hardware device)
Independent unit testing refers that each test should not depend on the result of other test.
Mock external dependencies is replacing complex dependencies for a simple one: I.E replace a DataBase to a Mock that hardcode the result.
Hope it helps.

Exactly what is integration testing - compared with unit

I am starting to use unit testing in my projects, and am writing tests that are testing at the method/function level.
I understand this and it makes sense.
But, what is integration testing? From what i read it moves the scope of testing up to test larger features of an application.
This implies that I write a new test suite to test larger things such as (on an e-commerce site) checkout functionality, user login functionality, basket functionality. So here i would have 3 integration tests written?
Is this correct - if not can someone explain what is meant.
Also, does integration test involve the ui (web application context here) and would employ the likes of selenium to automate. Or is integration testing still at the code level but tying together difference classes and areas of the code.
Consider a method like this PerformPayment(double amount, PaymentService service);
An unit test would be a test where you create a mock for the service argument.
An integration test would be a test where you use an actual external service so that you test if that service responds correctly to your input data.
Unit tests are tests that the tested code is inside of the actual class. Another dependencies of this class are mocked or ignored, because the focus is test the code inside the class.
Integration tests are tests that involves disk access, application service and/or frameworks from the target application. The integration tests run isolated from another external services.
I will give an example. You have a Spring application and you made a lot of unit tests to guarantee that the business logic is working properly. Perfect. But what kind of tests you have to guarantee:
Your application service can start
Your database entity is mapped correctly
You have all the necessary annotations working as expected
Your Filter is working properly
Your API is accepting some kind of data
Your main feature is really working in the basic scenario
Your database query is working as expected
Etc...
This can't be done with unit tests but you, as developer, need to guarantee that all things are working too. This is the objective of integration tests.
The ideal scenario is the integration tests running independent from another external systems that the application use in a production environment. You can accomplish that using Wiremock for Rest calls, a memory database like H2, mocking beans from some specific classes that call external systems, etc.
A little curiosity, Maven have a specific plugin for Integration Tests: the maven failsafe plugin, that execute test classes that the name ends with IT (by default). Example: UserIT.java.
The confusion about what Integration Test means
Some people understand the "integration test" as a test involving the "integration" to other external systems that the currently system use. This kind of tests can only be done in a environment where you have all the systems up and running to attend you. Nothing fake, nothing mocked.
This might be only a naming problem, but we have a lack of tests (what I understand as integration tests) that attends the necessity of the items described above. On contrary, we are jumping for a definition of unit tests (test class only) to a "integration" test (the whole real systems up). So what is in the middle of it if not the integration tests?
You can read more about this confusion on this article by Martin Fowler. He separates the "integration tests" term on two meanings: the "broad" and "narrow" integration tests:
narrow integration tests
exercise only that portion of the code in my service that talks to a
separate service
uses test doubles of those services, either in
process or remote
thus consist of many narrowly scoped tests, often no
larger in scope than a unit test (and usually run with the same test
framework that's used for unit tests)
broad integration tests
require live versions of all services, requiring substantial test
environment and network access
exercise code paths through all
services, not just code responsible for interactions
You can get even more details on this article.
Unit testing is where you are testing your business logic within a class or a piece of code. For example, if you are testing that a particular section of your method should call a repository your unit test will check to make sure that the method of the interface which calls the repository is called the correct number of times that you expect, otherwise it fails the test.
Integration testing on the other hand is testing that the actual service or repository (database) behavior is correct. It is checking that based on data you pass in you retrieve the expected results. This ties in with your unit tests so that you know what data you should retrieve and what it does with that data.
As far as I see the selenium tests should be in another test suite. Those tests are the most fragile test in nature even if you write them correctly. Here you can use Specflow or some other kind of specification by example framework. Perhaps you can call these tests as acceptance tests. These are for developers and business experts too.
The integration, or module tests normally do not use UI. The integration tests exercise some classes which are working together. These are lower level tests than the selenium tests, and a bit easier to maintain. These tests are for developers only.
Here are a couple of constraints that a good unit test satisfies. Meeting these constraints also required good testable code.
No I/O - disk or network
Only one assertion (if multiple, they should be minor variations of each other)
Does not exercise (cover) much more production code than what it asserts
These constraints usually don't apply to integration tests.

Is mocking an essential part of unit testing?

I have a web service which calls a third party web service.
Now I want to unit-test my web service. For this, should I mock the third party web service or is it fine to call it during the tests?
Is there any standard document on unit testing?
Yes, you should mock the third party web service for unit testing. Here are some advantages:
Your unit tests are independent of other components and really only test the unit and not also the web service. If you include the service in your unit tests and they fail, you won't know whether the problem is in your code or in the foreign web service.
Your tests are independent of the environment. If the Internet connection is ever down or you want to test on a machine that doesn't have Internet access at all, your test will still work.
Your tests will be much faster without actually connecting to the web service. This might not seem like a big thing but if you have many many tests (which you should), it can really get annoying.
You can also test the robustness of your unit by having the mock send unexpected things. This can always happen in the real world and if it does, your web service should react nicely and not just crash. There is no way to test that when using the real web service.
However, there is also integration testing. There, you test the complete setup, with all components put together (integrated). This is where you would use the real web service instead of the mock.
Both kinds of testing are important, but unit testing is typically done earlier and more frequently. It can (and should) be done before all components of the system are created. Integration testing requires a minimal amount of progress in all of most of the components.
This depend on what you're unit-testing.
So if you're testing out whether you can successfully communicate with the third-party webservice, you wouldn't obviously try to mock this. However if you're unit-testing some business use-cases that are part of your web-service offering (unrelated to what the other modules/web services are doing), then you might want to mock the third-party web service.
You should test both but both test cases does not fall under Unit testing.
Unit testing is primarily used for testing individual smaller pieces i.e. classes and methods. Unit testing is something that should preferably happen during the build process without any human intervention. So as part of Unit testing you should mock out the third party webservice. The advantage of mocking is that you can make the mocked object behave in many possible ways and test your classes/methods to make sure they handle all possible cases.
When multiple systems are involved, the test case falls under System/Integration/Functional testing. So as part of your System/Integration/Functional testing, you should call the methods in other webservice from your webservice and make sure everything works as expected.
Mocking is an usually essential in unit testing components which have dependent components. This is so because in unit testing , you are limited to testing that your code works correctly ( does what its contract says it will do ). If this method , in trying to do the part of its contract depends upon other component doing their part correctly , it is perfectly fine to mock that part out ( assuming that they work correctly ).
If you dont mock the other dependent parts , you soon run into problems. First , you cannot be certain what behavior is exhibited by that component. Second , you cannot predict the results of your own test ( because you dont know what was the inputs supplied to your tests )

Categories

Resources