JUnit test on setters and getters failing - java

i'm getting a nullpointerexception when i run the junit test in eclipse. what am i missing here?
MainTest
public class MainTest {
private Main main;
#Test
public void testMain() {
final Main main = new Main();
main.setStudent("James");
}
#Test
public void testGetStudent() {
assertEquals("Test getStudent ", "student", main.getStudent());
}
#Test
public void testSetStudent() {
main.setStudent("newStudent");
assertEquals("Test setStudent", "newStudent", main.getStudent());
}
}
setters and getters are in the Main class
Main
public String getStudent() {
return student;
}
public void setStudent(final String studentIn) {
this.student = studentIn;
}
thanks.

You need to initialize your main object before using it
You can do it either on an #Before method or inside the test itself.
OPTION 1
Change
#Test
public void testSetStudent() {
main.setStudent("newStudent");
assertEquals("Test setStudent", "newStudent", main.getStudent());
}
to
#Test
public void testSetStudent() {
main = new Main();
main.setStudent("newStudent");
assertEquals("Test setStudent", "newStudent", main.getStudent());
}
OPTION 2
Create a #Before method, when using #Before the main field will be created before any #Test is executed, there is another option, option 3, to use #BeforeClass
#Before
public void before(){
main = new Main();
}
OPTION 3
#BeforeClass
public static void beforeClass(){
//Here is not useful to create the main field, here is the moment to initialize
//another kind of resources.
}

Every test method gets a new instance of MainTest. This means that the changes you make in your first method won't show up in your second method, and so on. There is no sequential relationship between one test method and another.
You need to make each method a self-contained test that tests one aspect of your class's behaviour.

Related

JUnit makes a new instance of the class without #BeforeEach?

In order to refactor testing, we are taught that JUnit will make a new instance of the class every time by doing the following:
public class someClassTest{
final private someClass obj1 = new someClass();
#Test
public void t1() {
Assertions.assertEquals(1, obj1.returnOne());
}
#Test
public void t2() {
Assertions.assertEquals(8, obj1.return(2));
}
}
Rather than using something like
#BeforeEach
void setup(){
someClass obj1 = new someClass();}
or initializing it inside the test methods every time.
My question is, why and how does my first block of code work to achieve the same purpose as the #BeforeEach?
JUnit framework manages that. It creates a new instance of the test class (someClassTest) before each test.
Take a look at this example:
public class SampleTest {
#Test
public void test1() {
System.out.println(this.toString());
}
#Test
public void test2() {
System.out.println(this.toString());
}
}
Run it and you'll see that the test class instance is different in test1 and test2, for example:
SampleTest#4e515669
SampleTest#504bae78
From that point is just an ordinary behavior of Java.
If you have a field in an object, it will be re-created (and re-initialized):
public class SampleTest {
private int i = 0;
#Test
public void test1() {
// i is 0, so lets increase and see what happens in test2
i++;
}
#Test
public void test2() {
// here i is again 0 because it was re-created, we have a different object of SampleTest
}
}

Testing console output

Got a question regarding testing the console output.
stdOutput class:
public abstract class StdOutTest {
private final PrintStream stdOutMock = mock(PrintStream.class);
private final PrintStream stdOutOrig = System.out;
#Before
public void setUp() {
System.setOut(this.stdOutMock);
}
#After
public void tearDown() {
System.setOut(this.stdOutOrig);
}
protected final PrintStream getStdOutMock() {
return this.stdOutMock;
}
}
Now here is something I don't understand:
public class test extends StdOutTest{
#Before
public void setUp(){
//empty
}
#Test
public void example(){
System.out.println("hello");
verify(getStdOutMock()).println("hello");
}
}
I use Mockito for the verify and this test passes when I delete setUp(), but with the setUp() it fails. the fail message says:
hello
Wanted but not invoked:
printStream.println("hello");
-> at observer_test.test.example(test.java:18)
Actually, there were zero interactions with this mock.
Can anyone help me perhaps on why this happens?
Your subclass is overriding the setUp method of the superclass with an empty method. You can fix this by adding a call to the superclass method:
#Before
public void setUp(){
super.setUp();
}
Or you can just delete the setUp method in the subclass it if you don't need to perform any custom setup in there.

TestNG one test for two classes

I have TestNG tests in some classes, which extends the same main class.
I need the same last test for class1 and class2, but if I add #Test(priority = 666) to main class it start after all classes.
How I should annotate #Test in main class what would it starts after all tests of each class?
Big thanks. Also sorry for bad english.
main class
public class MainTest {
#BeforeClass()
public void setup() {
//something
}
#AfterClass()
public void tearDown() {
//something
}
#AfterMethod()
public void log_writer(Method method) {
//something
}
#Test(priority = 666) {}
}
class1
public class Class1 extends MainTest {
#Test
public void test1(){}
#Test
public void test2(){}
}
and class2
public class Class2 extends MainTest {
#Test
public void test1(){}
#Test
public void test2(){}
}
what you are looking for is the #AfterClass annotation. handle the part where you want to check logs in the AfterClass annotated method
It's not possible. Basically each #Test runs only once. If you need to do something after each test class you have to use #AfterClass annotation on method in your MainTest. You can do some hacks with method order etc. in MethodInterceptor (http://testng.org/doc/documentation-main.html#methodinterceptors) but it's not good idea for this case.

JUnit Enclosed runner and shared setup

I'm experimenting with the JUnit Enclosed runner in order to try and improve the organisation of some of my tests. At the moment I'm trying to work out how to share some setup between the inner classes.
Attempt the first:
#RunWith(Enclosed.class)
public class EnclosedTest {
#Before
public void printSomething() {
System.out.println("Helllooo Meggan");
}
public static class FirstTest {
#Test
public void assertThatSomethingIsTrue() {
assertThat(true, is(true));
}
}
public static class SecondTest {
#Test
public void assertThatSomethingIsFalse() {
assertThat(false, is(false));
}
}
}
Unfortunately, no-one says hello to Meggan. If I update an inner class to extend the outer one, then I get the following:
java.lang.Exception: class 'org.scratch.EnclosedTest$FirstTest' (possibly indirectly) contains itself as a SuiteClass
at org.junit.runners.model.InitializationError.<init>(InitializationError.java:32)
Is there a particular Enclosed idiom to use when trying to share setup between inner test classes? I was hoping it would be as simple as the C# example I found.
Enclosed runner internally works as a Suite, that is, it runs the classes as Test cases. And since Junit 4.12 abstract inner classes are ignored by Enclosed runner.
That said the way to share set up is to create an abstract class containing it (#Before, #After):
#RunWith(Enclosed.class)
public class EnclosedTest {
abstract public static class SharedSetUp {
#Before
public void printSomething() {
System.out.println("Helllooo Meggan");
}
}
public static class FirstTest extends SharedSetUp {
#Test
public void assertThatSomethingIsTrue() {
assertThat(true, is(true));
}
}
public static class SecondTest extends SharedSetUp {
#Test
public void assertThatSomethingIsFalse() {
assertThat(false, is(false));
}
}
}
Notice that you can even declare custom runners for each subclass.

java.lang.IllegalStateException: missing behavior definition for the preceding method call getMessage("title")

I'm using EasyMock(version 2.4) and TestNG for writing UnitTest.
I have a following scenario and I cannot change the way class hierarchy is defined.
I'm testing ClassB which is extending ClassA.
ClassB look like this
public class ClassB extends ClassA {
public ClassB()
{
super("title");
}
#Override
public String getDisplayName()
{
return ClientMessages.getMessages("ClassB.title");
}
}
ClassA code
public abstract class ClassA {
private String title;
public ClassA(String title)
{
this.title = ClientMessages.getMessages(title);
}
public String getDisplayName()
{
return this.title;
}
}
ClientMessages class code
public class ClientMessages {
private static MessageResourse messageResourse;
public ClientMessages(MessageResourse messageResourse)
{
this.messageResourse = messageResourse;
}
public static String getMessages(String code)
{
return messageResourse.getMessage(code);
}
}
MessageResourse Class code
public class MessageResourse {
public String getMessage(String code)
{
return code;
}
}
Testing ClassB
import static org.easymock.classextension.EasyMock.createMock;
import org.easymock.classextension.EasyMock;
import org.testng.Assert;
import org.testng.annotations.Test;
public class ClassBTest
{
private MessageResourse mockMessageResourse = createMock(MessageResourse.class);
private ClassB classToTest;
private ClientMessages clientMessages;
#Test
public void testGetDisplayName()
{
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
clientMessages = new ClientMessages(mockMessageResourse);
classToTest = new ClassB();
Assert.assertEquals("someTitle" , classToTest.getDisplayName());
EasyMock.replay(mockMessageResourse);
}
}
When I'm running this this test I'm getting following exception:
java.lang.IllegalStateException: missing behavior definition for the preceding method call getMessage("title")
While debugging what I found is, it's not considering the mock method call
mockMessageResourse.getMessage("ClassB.title") as it has been called from the construtor (ClassB object creation).
Can any one please help me how to test in this case.
Thanks.
You need to call EasyMock.replay(mock) before calling the method under test. After calling the method under test you can call EasyMock.verify(mock) to verify the mock is called.
Next you need to add another expect call with the "title" argument since you call it twice.
Code:
EasyMock.expect(mockMessageResourse.getMessage("title")).andReturn("title");
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
EasyMock.replay(mockMessageResourse);
clientMessages = new ClientMessages(mockMessageResourse);
classToTest = new ClassB();
Assert.assertEquals("someTitle" , classToTest.getDisplayName());
EasyMock.verify(mockMessageResourse);
In my case, it was caused by the omission of a return value specification (andReturn(...)).
http://www.smcmaster.com/2011/04/easymock-issue-1-missing-behavior.html for more details.
This can have various causes (someMock is the name of your mocked Object in this answer).
On the one side it can be that you need to expect the call via
expect(someMock.someMethod(anyObject()).andReturn("some-object");
like in Reda's answer.
It can also be that you forgot to call replay(someMock) before you used the mock, like you can see in Julien Rentrop's answer.
A last thing that is possible that wasn't mentioned here is that you used the mock somewhere else before in a test and forgot to reset the mock via reset(someMock).
This can happen if you have multiple Unit Tests like this:
private Object a = EasyMock.createMock(Object.class);
#Test
public void testA() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
#Test
public void testB() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
This will fail on one test with the IllegalStateException, because the mock a was not reset before being used in the next test. To solve it you can do the following:
private Object a = EasyMock.createMock(Object.class);
#Test
public void testA() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
#Test
public void testB() throws Exception {
expect(a.someThing()).andReturn("hello");
replay(a);
// some test code and assertions etc. here
verify(a);
}
#After
public void tearDown() throws Exception {
reset(a); // reset the mock after each test
}
You should put your call to replay after the expect calls, and before you use your mock. In this case you should change your test to something like this:
#Test
public void testGetDisplayName()
{
EasyMock.expect(mockMessageResourse.getMessage("ClassB.title")).andReturn("someTitle");
EasyMock.replay(mockMessageResourse);
clientMessages = new ClientMessages(mockMessageResourse);
classToTest = new ClassB();
Assert.assertEquals("someTitle" , classToTest.getDisplayName());
}
For me, this exception was occurring because the method I was trying to stub was final (something I hadn't realized).
If you want to stub a final method you'll need to use Powermock.

Categories