Best practice for naming unit and integration test methods? - java

I've recently inherited an application that is written by different people at different times and looking for guidance on how to standardize.

Assuming NUnit:
[Test]
public void ObjectUnderTest_StateChanged_Consequence()
{
Assert.That(tra_la_la);
}
[Test]
public void ObjectUnderTest_Behaviour_Consequence()
{
Assert.That(tra_la_la);
}
for example:
[Test]
public void WifeIsTired_TakeWifeToDinner_WifeIsGrateful()
{
Assert.That(tra_la_la);
}
[Test]
public void WifeIsTired_MentionNewGirlfriend_WifeGetsHalf()
{
Assert.That(tra_la_la);
}

I just write what it's for. It's not like you're going to have to type the names in anywhere else, so having a testWibbleDoesNotThrowAnExceptionIfPassedAFrobulator isn't a problem. Anything which is a test begins with 'test', obviously.

There is no standard as such, different people/places will have different schemes. The important thing is you stick to a standard.
Personally I'm a fan of the following - example code in C#, but very close to Java, same rules apply:
[Test]
public void person_should_say_hello()
{
// Arrange
var person = new Person();
// Act
string result = person.SayHello();
// Assert
Assert(..., "The person did not say hello correctly!");
}
Explicit
The test name should give the name of the class under test. In this example, the class being tested is Person. The test name should also have the name of the method that is being tested. This way, if the test was to fail, you'll at least know where to look to solve it. I'd also recommend following the AAA - Arrange, Act, Assert rule, it will ensures your tests are easy to read and follow.
Friendly fail messages
When it comes to asserting a result/state, its useful to include an optional message. This makes it easier when a test fails, especially when run as part of a build process or via an external tool.
Underscores
The final (though optional) stance I follow is using underscores for tests names. While I'm no fan of underscores in production code, their use in test names is useful as test names are often much longer. Quickly glancing at a test name that uses underscores proves to be much more readable, though this is subjective and the source of much debate with regards unit testing practices.
Integration Tests
The same standards apply to integration tests, the only difference being the location of such tests should be separate from unit tests. In the example code above, the test class would be called PersonTests and located in a file called PersonTests.cs. The integration tests would be named in a similar manner - PersonIntegrationTests, located in PersonIntegrationTests.cs. The same project can be used for these tests, but ensure they are located in separate directories.

It's instructive to look at BDD (behavioural driven development) and this blog post in particular.
BDD is essentially focusing on components and what they should do. Consequently it impacts directly on how you name/structure your tests, and the code they use to set up conditions and validate. BDD allows not only the developers to read/write the tests, but non-technical members of the team (business analysts etc.) can contribute by specifying the tests and validating them.

I ran across two good suggestions. Links here: http://slott-softwarearchitect.blogspot.com/2009/10/unit-test-naming.html
http://weblogs.asp.net/rosherove/archive/2005/04/03/TestNamingStandards.aspx
http://openmrs.org/wiki/Unit_Testing_with_#should

In that situation I'd probably find the naming convention that was used the most and refactor the rest of the code to use that. If the one that was used the most is truly horrid, I'd still look to the existing code and try to find one that I could live with. Consistency is more important than arbitrary conventions.

I use a FunctionTestCondition construct. If I have two methods, Get and Set I would maybe create the following test methods:
GetTest being a positive test (everything is ok).
GetTestInvalidIndex to test an invalid index being passed to the method.
GetTestNotInitialized to test when the data is not inited before use.
SetTest
SetTestInvalidIndex
SetTestTooLargeValue
SetTestTooLongString

Group your tests by setup, make a test class around this setup and name is with suffix Test or IntegrationTest. Using a test framework like JUnit or TestNG you can name your test methods as you want. I would name the method as what it tests, a sentence in camel case, not test prefix. The frameworks use a #Test annotation to mark a method as test.

Related

How to mock an internal variable with builder

I am writing unit tests and meet a problem with builder:
Here is the class to be test:
public class ToBeTest() {
public void enact(SomeInput input){
Session s = Session.builder().attributeA(input.getA()).build();
s.attributeB("someValue");
}
}
How can I write a test to verify whether Session S set field A and also B successfully? Thanks!
Basically there are two things you can verify on:
input.getA(): mock that instance of SomeInput you provide to your code under test, then you can verify that mocked object later on!
Session.builder() is most likely a static call, so use static mocking to provide a mocked builder object, which you can verify later on, too. See the official documentation for the steps required to do that.
Having said that: your real problem is that you wrote "hard to test code". Surprise, that makes it hard to test. You see, what is the point of having a "method local" Sessions variable in the first place. If that method would return that s, you could then check if it has certain properties. Or if s would be a field of that class, you could then maybe do other checking, to ensure that a correctly configured Session was build.
Long story short: PowerMock(ito) offers the things you need to this code. Read some good tutorials and you shouldn't have much issues. But it would be worthwhile to also invest into improving your code under test to make it easier to test. My rule of thumb is: when you need PowerMock(ito) to test your code, then your production code should be improved.

How to mock ArrayList class using using whenNew method

I'm trying to mock arraylist to verify the add method but I'm getting the message:
FAILED: testInit
Wanted but not invoked:
arrayList.add(<any>);
-> at AsyncRestTemplateAutoConfigurationTest.testInit(AsyncRestTemplateAutoConfigurationTest.java:95)
Actually, there were zero interactions with this mock.
The test class I've used is:
#Test
public void testInit() throws Exception {
ArrayList<AsyncClientHttpRequestInterceptor> interceptors = Mockito.mock(ArrayList.class);
PowerMockito.whenNew(ArrayList.class).withAnyArguments()
.thenReturn(interceptors);
Mockito.stub(interceptors.add(Mockito.any())).toReturn(true);
asyncRestTemplateAutoConfiguration.init();
Mockito.verify(interceptors).add(Mockito.any());
}
The actual tested code is:
List<AsyncClientHttpRequestInterceptor> interceptors = new ArrayList<>(interceptors);
interceptors.add(new TracingAsyncRestTemplateInterceptor(tracer));
I've declared the test class with
#RunWith(PowerMockRunner.class)
#PrepareForTest(AsyncRestTemplateAutoConfiguration.class)
Where AsyncRestTemplateAutoConfigurationis the class, which I'm using to test. Could anyone please tell me what I'm missing?
Your unit test should verify public observable behavior which is return values and communication with dependencies (which does not nessessarily imply to test only public methods).
That your production code uses an ArrayList to store your data is an implementation detail which you don't want to test since it may be changed without changing the units general behavior, in which case your unittest should not fail.
Don't start learning how to unit test using PowerMockito - it will give you bad habits.
Instead, consider working carefully through the documentation for Mockito and you will see how to structure your classes for better testing.
Ideally, your classes should be such that you do not need PowerMockito to test them and you can just rely on plain old Mockito.
If you can arrive at the point where you can write elegant and simple tests using just Mockito, it will be a sign you have grasped the fundamental concepts of unit testing.
You can start by learning how to inject dependencies through the constructor of the class that can be swapped with mocked test doubles on which behaviour can be verified.
Another point to note is, as per the other answer, the internal ArrayList in your system under test is an implementation detail. Unless consumers of your system under test can access the ArrayList through, say, methods that expose it there is not much point in writing a test against it.
If the state of the internal ArrayList affects something from the point of view of the consumer, then try writing a test against that rather than against the internal property.
Good luck with your journey on unit testing!

Junit Test annotation vs test suffix or prefix

I developed a java application and I want to write unit test for it. (I have never written a unit test in java before) I noticed that there are 2 different example by writing Junit test. like E.g. 1
public void testExample(){
//do something...
}
than E.g. 2
#Test
public void Example(){
//do something...
}
which one is the more usefull ?
Test convention have changed in JUnit4
There's no need for test prefix anymore, just use #Test annotation before the method:
JUnit 3 used naming conventions for the identification of test methods. JUnit 4 uses annotations for that purpose, so that the prefix "test" is actually superfluous. It is not only superfluous, but also redundant.
Instead writing something like:
#Test
public void testAverageTotalStartedThreadCount() {}
you could just skip the prefix "test" and go with the annotation only:
#Test
public void averageTotalStartedThreadCount() {}
The "test" prefixes are still generated by Eclipse and NetBeans, so if you don't like the superfluous naming, you will have to remove it manually. The "test" prefix in the test-class name, however, is still useful. It makes the search for test classes more easy.
For example 1, I assume you are planning to throw exception or log if something goes wrong.
Although you can do it, but the preferred way is to write proper unit test using frameworks like Junit (#Test is from Junit framework).
Junit framework makes testing easier and is considered standard in Java Development. You can use features like Assert to check the output of method or fields inside it. Thus Ex 2 is preferred in industry. refer this test file written using junit framework -
https://github.com/akashchandwani/Algorithms/blob/master/Algorithms/test/sorting/SortingTest.java .
Here's a junit tutorial you can refer to, there are several available on web, you can choose what suits you.
http://www.vogella.com/tutorials/JUnit/article.html

How do you do unit tests for getters and setters?

I am new to tdd and the mockito web framework.
Basically this is the getter method in the class:
public Long getDeviceManufactureId()
{
return deviceManufacturerId;
}
How would I write a unit test?
so far I am thinking this:
dem is the name of the class
#Test
public void testGetDeviceManufactureIdreturnsDeviceManufactureId()
{
assertEquals("Richard", dem.getDeviceManufactureId());
}
In general we write test cases for methods that has some logic in it. Like service methods that may have multiple dao calls. Simply writing test cases for all method does not make sense and usually wastage of time in build (however small that is). So my opinion would be not to write such trivial test cases.
If it is just about code coverage then I am sure getter/setters will be used in some other method that will have a test for it. That should cover these. But if you absolutely have to write a test case then what you have done seems fine. You can also assert not null if the instance variable can never be null.
Testing getters and setters could be a requirement in certain though rare scenarios where the container class is not just a POJO.
If that is a case,I would recommend creating a single TestSuite,dedicated to such instance variables,with each testcase's naming convention like :
TestGetVariableNameClassName
TestSetVariableNameClassName
You need to organize the test data such as maintenance is not tricky.

How to write a UT to mock an internal object in one method?

For example , I have a java class as below. I am going to write a unit test for doWork(), so I would like to control obj's behavior. But it is obvious that obj is instantiated internally.
How can I write this UT? Now I am using Junit+Mockito.
class ToBeTest{
public ToBeTest(){}
public boolean doWork(){
OtherObject obj=new OtherObject();
return obj.work();
}
}
Thanks in advance. :)
BTW, The reality is I am writing UT for other person's class. So I don't want to change it. It has been fully tested by integration test.
If you can't change the code, you can use Powermock along with junit and Mockito to mock the construction of new objects.
#Test
public void testDoWork() throws Exception{
MyTest mytest = new MyTest();
OtherObj obj = new OtherObj();
obj.test="mocked Test"; //here you can add any other needed values to obj
PowerMockito.whenNew(OtherObj.class).withNoArguments().thenReturn(obj);
String result = mytest.doWork();
Assert.assertTrue(result.equalsIgnoreCase("mocked Test"));
}
The best way is to write code to support testing (Test-Driven Development is emphasizing this). At the moment, your code is written in the way which makes it difficult to test.
Please consider using dependency injection, because it helps you mock the dependent object.
This is a classical example where you should use dependency injection.
In short, instead of creating the object (dependency) internally, you pass it in the constructor or use a factory to create what you want (the factory returns the real implementation in production code and another in test). This gives you the possibility to change the implementation when you test.
Look at the examples following the like I provided or google for "Java dependency injection example".
You can't easily. I can think of two ways you can do this and neither are supported out of the box by Mockito or jUnit as far as I'm aware:
1) Byte code manipulation using cglib or similar library which would be moderately difficult to do and likely pretty fragile.
2) Alternate classloader. You can build a classloader that looks for an attempt to load the OtherObject class and replaces it with an anonymous OtherObject class that gives you the mocking behavior that you are looking for.
Most of the time you should be treating it as a dependency though. If you want to test opening a file, you probably actually want to test with a file so using the concrete class is probably fine. If you want to test a method's behavior that has opening a file as a part of it's logic, you could easily move that out to a dependency and then mock it out. In fact, that usually makes sense because what you store in a file one day, may need to be stored in a database another or be pulled down from the cloud on a third day, so segregating the logic around what you do with the file from the actual process of opening a retrieving the contents is often a logical separation of concerns anyway.
It's very easy:
import org.junit.*;
import mockit.*;
#Test
public void justMockIt()
{
new NonStrictExpectations() { OtherObject o; { o.work(); result = true; }};
assert new ToBeTest().doWork();
}
... when using JMockit.
You have written your code, and now you want to unit test it. This is the fundamental cause of your difficulty. I suggest a different approach.
Express what the doWork() method is meant to do in terms of behaviour that can be observed only through public and protected (getter) methods of the ToBeTest class, or the public and protected methods of any objectys associated-with ToBeTest objects. Take a look at the Javadoc provided with the Java library: that describes what all those classes do without stating the bodies of the methods. When does yor method return true? When does it return false? What side effects does it have? You might find you need to add some getter methods to do this. You could express these in the Javadoc for your own code.
Use the required behaviour to decide what kinds of assertions you can place in your unit-tests.

Categories

Resources