Using #Before method in JUnit - java

I saw this question: Repeating code in JUnit tests earlier today. How do you write this code when you are starting? You see that there is a method addDrivingRecord(...). This method does not exist when you first start writing so do you make that test, ensure that it works, then proceed with setUp() method, or do you instead wait until you have written the addDrivingRecord(...) method and then refactor it to the #Before? I will explain further if needed.

If I understood well your asking if you should:
use addDrivingRecord in the test method
ensure it goes green (it works)
refactor addDrivingRecord to #Before
or
use addDrivingRecord in the test method
refactor addDrivingRecord to #Before
ensure it goes green (it works)
If it's your question I should go for the first option: first use method, then implement and go green, then refactor your test.
Because two reasons:
You should test/implement one thing at a time, so you will write one test method. Then you will make it green. Only then you should write another method and realize that code can be refactored in a #Before
A good practice is write test methods and only when you realize there are common things move them to #Before. That way you don't enforce innecesary things in initialization. Moreover, if you find that another test needs a very different #Before method it probably belongs to another test class.

Related

Should I use the same variables throught entire Unit Test?

I am creating Unit Tests in Java and for each method, I create the same lists, variables, etc. On the other hand, of course I thought that I could create all of these variables as global and set their values in the setup() method (in #Before), but I am not sure if the values may be changed when running tests due to multithreading, etc. So, what is the best way for this situation?
Nothing to worry about. JUnit will create a new instance of your test class, and then run each #Before method, and only then run the #Test method, and it does that song and dance routine all over again for every #Test annotated method in that class. You're using #Before exactly as it was intended: It's for storing initialization code that is required for all the tests in that test class.
JUnit does it this way because 'test independence' is nice to have: Tests, preferably, fail or pass independent of the ordering in which you execute them.
Every so often the init process is so expensive that it's not worth it to pay the 'cost' of running it over and over again for every test. The annotation #BeforeClass exists specifically for that purpose. The javadoc of #BeforeClass even spells out that this compromises test independence and should therefore only be used if the setup work you do within such a method is sufficiently expensive (computationally or otherwise) to make that tradeoff.
In other words:
Your worries about test independence are real, but they apply to #BeforeClass. #Before doesn't suffer from this problem; that code is re-run for every test.
NB: You can toss all this out the window if you have static stuff going on. Don't have static stuff in test code unless you really know what you're doing. I assume you don't have that in which case - carry on, your tests are independent.

How to verify one from many conditions is satisfied on Mockito? Is it possible to verify if one OR another method was called?

On my unit test I want to check if one or another method was called. I can easily verify how many times some methods are called thanks to Mockito, but verify has no verification mode like "OR". Any workarounds?
In my case I want to check if on SharedPreferences.Editor was called .apply() or .commit() because two of this possibilities satisfies me and saves data. Unfortunately if I call verify(mEditor).apply() but someone will change implementation to .commit() in example due to requirement of instant save, the test will fail, but shouldn't because I want to only test from this point of view if data are saved or not. It's the unit test and should be independent from changes like that and checks only scope of what are tested inside.
The work around you ask for would be to catch the underlying MockitoAssertionError (or just AssertionError):
try {
verify(mEditor).apply();
} catch (MockitoAssertionError mae) {
// apply was not called. Let's verify commit instead.
verify(mEditor).commit();
}
Alternatively, if both apply and commit call some (internal) save method you could also try verifying that (assuming it is exposed -- mock-based testing can be at odds with information hiding). Or, if you have control over the code you're testing you could refactor it along these lines.
The better advice, though, would be to avoid the need for this altogether, as argued in the answer by #GhostCat.
I am not aware of a good way of doing that, and honestly, I think the real answer is: do not do that. Yes, the other answer shows a way to achieve what you ask for, but then:
You know what your production code should be doing. Meaning: instead of writing a single piece of verification code that allows "this or that", rather write two independent tests, one for "this", and one for "that".
In other words: you control what goes into your tests. So write one test that should result in apply(), and one that should result in commit(). And then verify() that one case that each test is expected to see!
Unit tests should be straight forward. When something fails, you quickly look at the unit test and you already know where to look in the production code to spot the root cause. Anything that adds complexity to your tests might make that harder. It is better to have two tests that follow a clear "when then verify" path, instead of having one (or multiple) tests that go "when then verify this OR verify that".

Writing junits in Test Driven Development before writing actual code?

Folks it is always said in TDD that
we should write junits even before we write the actual code.
Somehow I am not able to understand this in right spirit. I hope what it means is that you just write empty methods wih right signatures and your test case is expected to fail initially
Say in TDD approach i need to get the list of customers.
As per my understanding i will write the empty method like below
public List<CustomerData> getCustomers(int custId){
return null;
}
Now i will write junit test case where i will check the size as 10(that i am eactually expecting). Is this Right?
Basically my question is in TDD, How we can write junit test case before writing actual code?
I hope what it means is that you just write empty methods wih right signatures
Yes. And with most modern IDEs, if you write a method name which does not exist in your test, they will create a stub for you.
Say in TDD approach i need to get the list of customers. whats the right way to proceed?
Your example is not quite there. You want to test for a 0-length array, but you already return it: you should first return null, the test will obviously fail.
Then modify the method so that the test succeeds.
Then create a test method for customer add. Test fails. Fix it. Rinse. Repeat.
So, basically: with TDD, you start and write test that you KNOW will fail, and then fix your code so that they work.
Recommended read.
Often you'll write the test alongside the skeleton of the code. Initially you can write a non-functional implementation (e.g. throw an UnsupportedOperationException) and that will trigger a test failure. Then you'd flesh out the implementation until finally your test passes.
You need to be pragmatic about this. Obviously you can't compile your test until at least your unit under test compiles, and so you have to do a minimal amount of implementation work alongside your test.
Check out this recent Dr Dobbs editoral, which discusses exactly this point and the role of pragmatism around this, especially by the mavens of this practise (Kent Beck et al)
A key principle of TDD is that you write no code without first writing
a failing unit test. But in fact, if you talk to the principal
advocates of TDD (such as Kent Beck, who popularized the technique,
and Bob Martin, who has taught it to thousands of developers), you
find that both of them write some code without writing tests first.
They do not — I should emphasize this — view these moments as lapses
of faith, but rather as the necessary pragmatism of the intelligent
developer.
That's partly right.
Using an IDE (Eclipse, IntelliJ) you can create a test. In that test invoke a method (that does not exist) and using a refactoring tool create a method with the proper signature.
That's a trick that makes working with TDD easier and more fun.
According to Now i will write junit test case where i will check the size as 0. Is this Right? you should write a test that fails, and the provide proper implementation.
I think go write the test first, Think about the signature of the function while writing the test.
It's the same as writing the signature and then writing the test, But when inventing the signature of the function while writing the test will be helpful since you will have all information about the responsibility of the function and you will be able to come up with the proper signature.

JUnit Test Cases #Before and #After annotations

We are following below practices to write JUnit tests for our methods.
Each method will be having their own class which holds all the tests which are required for that method. For e.g.: class test {...}
#Before will consists of per-requisites setup for methods like "Entity" so that when we do Edit we don't need to copy/paste code for adding an entity at each method level.
Now here my question is, shall we delete all the data which we entered by writing code to trash test-data in #after method or just let it be?
I know we can make it configurable but what is best practice? keep it or delete it. As per my gut feeling deleting should be better as if there is some duplicate data already in db - it may trigger wrong true or false.
It depends on how much you adhere to the Don't Repeat Yourself principle. It's also worth remembering that you have #After called after each #Test and #AfterClass called after all the #Test have run. With this granularity, it should be simple to remove duplication but still split those tasks that should only run at the very end, or after each test.
As a best practice I would recommend to clear your data storage between every test, to guarantee each test is isolated from other tests.
This could be done with the #After method if you want to keep some of the settings alive (from the #BeforeClassfor example). It could also be done in the #Before method for example by overriding variables with a new instance for every test, if you do so you do not need a clean up after the tests.
To clean up your settings of the #BeforeClass method you should use #AfterClass for example to close a Database connection or something simular what only needed to be done once. But this is not needed for every kind of unit test.

java junit testing in a loop

I have a JUnit test that I would like to run from a main method. I would like to retrieve multiple records from a database (within the main method) and pass each record into the JUnit, using a data object, so that each record can be tested. Can I pass a data object into the run method of JUnit. If not what is the best way to accomplish this. There are so many different scenarios that I would like to use actual data from the database. There could be as many as 5000 or more records to test.
Thanks
Doug
Surely you are looking for Parameterized test case. You can do it easily by using JUnit instead of using main() method.
You need Parameterized to run your test.
It will run your test with different parameters by passing parameters via constructor.
Here is an easy article how to do that. You can also try the example in the documentation also, to understand how it works.
You want to use JUnit's Parameterized Tests. There's really no way to run a main method in a JUnit test case.
On top of the docs, here's a blog post which explains it a little better: http://ourcraft.wordpress.com/2008/08/27/writing-a-parameterized-junit-test/
I think that testing your main method is more along the lines of an integration test or a functional test. The same can be said for testing your database data. If you really want a unit test the firs step would be to refactor your main method using Extract Method to pull out the business logic you want to test.
Doing this gives you a few benefits. First can test your code in isolation (which is one of the more important properties of a good unit test). If you refactor out the business logic you'll know that you are only testing that code and that no other code is affecting your test. Second by having an isolated method you'll be able to easily mock the test data you are looking at by passing in different parameters to the method and make your assertions based on the known mock data.

Categories