Junit test for method with anonymous code block - java

I need write junit test for method which contains anonymous code block, where override some logic. In my test I need verify if that logic works as should.
for instance:
public void foo(Bar bar) {
Foo myFoo = giveMeFoo(bar, new FooCallBack() {
#Override
public boolean doSomeLogic(SomeObject obj) {
if (obj.xxx == null)
return false;
// do some algorithm
reutrn true;
}
});
}
FooCallBack is interface which is implemented in few methods and I need to write tests for them.
What I need:
mock SomeObject obj and test different cases
verify if it returned true or false for different bar object
Can you tell me how to do this? Thanks in advice.

Related

Mockito void doAnswer correct usage & purpose

Today I learned about Mockito and while playing around with it I found something I do not understand.
Say I would like to test the following piece of code:
public void stop(boolean showMessage) {
if(executor != null && !executor.isShutdown() && this.isRunning) {
if(showMessage) {
View.getSingleton().showMessageDialog(Constant.messages.getString("sessionchecker.stopmessage"));
}
executor.shutdownNow();
executor = null;
extension.getCountdownTimer().stopCountdown();
this.isRunning = false;
this.usersReady.clear();
}
}
Since the stop method is a void I would need to call doAnswer (If I understand correctly).
So I tried the following:
#Test
public void testStopIsRunningFalse() {
Mockito.when(controller.isRunning()).thenReturn(true); // Mock a running service
Mockito.doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
if(controller.isRunning()) {
// Normally would actually shut down service
Mockito.when(controller.isRunning()).thenReturn(false); // Service should stop
}
return null;
}
}).when(controller).stop(false);
controller.stop(false);
boolean expected = false;
assertEquals(expected, controller.isRunning());
}
I, however, do not understand what the purpose of a test like this would be. Why would I test it like this since this will never fail (the parameter isRunning is being set as I would expect it to be).
Basically I only need to test the state of certain fields (isRunning and executor for example). These fields do not have public getters or setters however..
Therefore, I think I misunderstand the usage of the deAnswer. Could someone help me out?
If I understand your code example, it appears you are mocking the object you want to test, which is a no-no 99.9% of the time. You generally only want to mock direct collaborators of the class you are testing. Collaborators consist of things such as injected services (or other injected fields), and arguments of the method you are testing -- essentially anything that represents initial state of your class under test before you invoke the method being tested.

MockedObject and Real Object give different results

I have started learning JUNIT.
Here is what i am trying to achieve.
I have a class which checks if the inputString is part of secretKey;
public class StringChecker {
public boolean isEqual(String name)
{
boolean isEqual = false;
if(getSecretKey().contains(name))
{
isEqual = true;
}
return isEqual;
}
public String getSecretKey()
{
return "OSKAR";
}
}
My test class is this
public class RandomCheck {
#Test
public void isEqualTest()
{
StringChecker stringChecker = mock(StringChecker.class);
when(stringChecker.getSecretKey()).thenReturn("james");
//assertEquals(true, new StringChecker().isEqual("OSKAR")); <----this test case passes
assertEquals(true, stringChecker.isEqual("james"));
}
}
When i use Mocked object it does not give me the expected result, hence failing the test. But when i use a real object it gives me expected result and passes the test.
Am i missing anything? Like any annotation
A mockito mock is an object having the interface of the mocked class, but not its implementation. Your StringChecker is mocked, meaning there is no implementation code making calls from isEqual to getSecretKey as you assume.
You could use mockito spy, See this SO question:
Mockito.spy() is a recommended way of creating partial mocks. The reason is it guarantees real methods are called against correctly constructed object because you're responsible for constructing the object passed to spy() method.
ROOKIE MISTAKE
Here's the rookie mistake i did (mentioned by Arnold).
I mocked the StringChecker class but i did not provide any implementation for isEqual(String) method.
And because there was no implementation, i was getting the default value. In this case false (return type of method is boolean).
Solution
Using static method spy(). (Again mentioned by #Arnold).
So here is what my working code looks like.
#Test
public void isEqualTest()
{
StringChecker stringChecker = new StringChecker();
StringChecker spy = spy(stringChecker);
when(spy.getSecretKey()).thenReturn("james"); // providing implementation for the method
assertEquals(true, spy.isEqual("james"));
}
What i learnt from it.
Just by mocking an object does not get your things done if you intend to use methods of mocked object (In simple terms PROVIDE IMPLEMENTATION for methods of mocked objects).
TIP
If you want to see the default value returned by mocked object, just call the method of mocked object in sysout(without giving implementation).
Hope it will help someone like me.Peace
An alternative way without mocking and with additional test cases:
#Test
public void isEqualTest() {
StringChecker stringChecker = new StringChecker() {
#Override
public String getSecretKey() {
return "james";
}
};
assertTrue(stringChacker.isEqual("james"));
assertTrue(stringChacker.isEqual("jam"));
assertTrue(stringChacker.isEqual("mes"));
assertFalse(stringChacker.isEqual("oops"));
}
BTW, the isEqual() can be simplified to one line:
public boolean isEqual(String name) {
return getSecretKey().contains(name);
}

How should I mock out a single method inside an object I'm trying to test?

I have a problem with a class that I am testing where in almost every method I want to test, one of the first things each method does is call this one specific method. This method that is called once by all of these other methods takes a long time to execute. I don't want to have to wait for this every time I run my tests, it really is just a huge waste of time.
I attempted to #Spy the method using Mocktio, but I ran into problems because the really long method doesn't return anything. Can someone suggest a good way to mock out a single method inside a class I am trying to test?
Example:
public class myClass {
public void methodOne() {
reallyLongMethod();
// More code
}
public void methodTwo() {
reallyLongMethod();
// More code
}
.
.
.
public void methodN() {
reallyLongMethod();
// More code
}
public void reallyLongMethod() {
}
}
This is the class I am trying to test. I want to test all of the 'methodX()' methods. I don't want to run reallyLongMethod everysingle time however.
So, is there a way to use Mockito 'Spy' to stub out reallyLongMethod()? Even though it doesn'treturn anything?
You can use a Spy with doNothing(), but make sure you use the spy during the test. Mockito spies copy the original, instead of delegating to it.
#RunWith(MockitoJUnitRunner.class)
public class YourTest {
// Option 1:
// #Spy MyClass myClass = new MyClass();
// Option 2 (see #Before method)
MyClass myClass;
#Before public void ignoreReallyLongMethod() {
myClass = spy(new MyClass()); // discard original
doNothing().when(myClass).reallyLongMethod();
}
#Test public void methodOneWorks() {
myClass.methodOne(); // you're using the spy here
assertEquals(42, myClass.getFoo());
}
}
Though this does evoke a code smell, don't mock or stub the class under test, as long as you're careful to test the method behavior (methodOne) and not the stubbed behavior (reallyLongMethod) you'll be good to go. If you do want to test reallyLongMethod you'll want to use a different object instance or else you'll "test" the doNothing() call alone. Do bear in mind that if reallyLongMethod and your other methods have any negative interactions, these tests won't tell you about that.
By the way, you can also do the equivalent without using Mockito, which may make a little clearer what you are or aren't doing with your mocks:
#RunWith(JUnit4.class)
public class YourTest {
MyClass myClass;
#Before public void createMyClass() {
myClass = new MyClass() { // create an anonymous inner class
#Override public void reallyLongMethod() {} // that does nothing here
};
}
}

Using Mockito test super class method

class Sup {
public void someMethod(){
// do something
}
}
class Sub extends Sup {
public void method(Object obj) {
if (obj == null) {
super.someMethod();
return;
}
// do something
}
}
class SubTest {
#Test
public void testMethodArgIsNull() {
Sub s = new Sub();
Sub spyS = spy(s);
spyS.method(null);
//test case fails
verify(spyS).someMethod();
}
}
if I redefine the method "method" in Sub like, instead of calling super.someMethod(), if i call someMethod(), the test case passed. But I don't want to make any changes in code. help me to test the code..
I don't know why you want to avoid changing code, but you may have your reasons. You can't simply verify that the super method was called on a spy. However, you may still be able to test this method without changing the code. The only way to do that, though, is without the spy. In other words, you will have to verify the functionality of someMethod with assertions or verifications on other mocks. For example, if the Sup class were implemented trivially thus:
class Sup {
private boolean somethingDone = false;
public boolean isSomethingDone() {
return somethingDone;
}
public void someMethod(){
somethingDone = true;
}
}
Then you could write your test case thus:
#Test
public void testMethodArgIsNull() {
Sub s = new Sub();
s.method(null);
assertThat(s.isSomethingDone(), is(true));
}
That being said, calling super.someMethod() from anything other than Sub.someMethod() (which doesn't exist) looks like a gotcha waiting to happen. If Sub.someMethod() does not exist, then super.someMethod() is equivalent to someMethod(). But, if someone were to override it in the future, would you really want method(Object o) to sneakily bypass the overridden one and call the super implementation anyway?
By calling super.someMethod() you gain nothing but risk future bugs.

How do you stub an individual method in java for unit testing?

I've got a method in a class that's writing to some string, which calls another method which does the same. Something like:
void foo() {
a += "xyx";
bar();
}
void bar() {
a += "abc";
}
For unit testing purposes, I want to test foo and bar separately. Is there any way to prevent bar from being run when I call foo() or to replace it with another method?
Create a subclass that overrides bar() that does nothing.
Why would you want to do that?
You could intercept the code at the byte code level using aspects (not wise); you could take in an object that calls bar: void foo(MyBarObject m) {
a += "xyx";
m.bar();
}
But, as I said, I can't think why this is useful. A unit test is meant to test a public interface. If bar() is private or protected, then it's tested automatically via your call, and later assertions, to foo(). If both foo() and bar() are public, cool, test them separatley.
Can you post a real example? Can you change the code under test? Etc.
One could argue that the above example isn't testable code. Instead, if the code were:
void foo() {
a += "xyx";
}
void bar() {
a += "abc";
}
void fooBar() {
foo();
bar();
}
it would be easy to unit test.

Categories

Resources