I want to make constructor.newInstance(...) throw an exception in a unit test. I'd like to check if the else-branch is reached in the following (dummy-)code:
public <T extends IInterface> instantiate(final Constructor<IInterface> constructor) {
try {
return constructor.newInstance(arg);
} catch (Exception e) {
return null;
}
}
I'd like to reach the null case. Can I mock that without using (Power)Mockito?
I could theoretically do
class TestImplementation implements IInterface {
public TestImplementation(Arg.class) {
throw new InstantiationException("just for your test case");
}
}
But I'm curious whether or not I can achieve this with mocking.
The class java.lang.Constructor is final, so mocking is hard by default. The latest versions of Mockito support mocking final classes, EasyMock does not to my knowledge.
Thus, your choices are probably:
Mockito (latest versions, with the new experimental "mocking of final" enabled)
PowerMock(ito)
JMockit
And for the record: passing in a Class instance of some "dummy" class, like you suggest within the question is way better than using a mocking framework.
You have to understand: you don't use mocking because you can. You only use it when you have to! In your case, there is a simple, straight forward non-mocking solution to test your production code.
So: use TestImplementation.class and forget about using a mocking framework here.
Related
I've got a class that looks like this:
public class Foo {
public meth() {
try {
privMethod();
System.out.println("Yay!");
} catch (FooException e) {
System.out.println("Boo!");
}
}
private void privMethod() throws FooException {
//doOtherStuff
if (someCondition()) {
throw new FooException();
}
}
private class FooException extends Exception {
FooException(String message) { super(message); }
}
}
I want to write a unit test for this, using Mockito and Powermock. I know I can mock the private method like this:
Foo spy = PowerMockito.spy(new Foo())
PowerMockito.doNothing().when(spy, "privMethod");
But how do I tell it to throw the exception? I know it'll be something like this:
Powermockito.doThrow(/*what goes here?*/).when(spy, "privMethod");
What goes there?
Note that the exception is a private inner class, so I can't just do doThrow(new FooException()), since FooException isn't accessible from the unit test.
In general, you go.
Powermockito.doThrow(theThingToThrow)
goes there. Like doThrow(new RuntimeException("should be thrown")) for example. Or a more specific exception, depending what you want the code under test to do about the exception.
But of course: you want to instantiate a private class there. Which you can't do (easily, see here for terribly complicated ways to do that). From that point of view: you created a very-hard-to-test design. The answer is to rework that design, making it easier to test.
And a final word of warning: I think you should not need to use PowerMockito for this. Spies work with plain Mockito.
And when there is no hard need to use the PowerMock(ito) versions, then do not use them. Period. They have their place, but honestly: most often, needing PowerMock(ito) equals to "hard to test code".
Beyond that: looking at private methods translates to testing implementation details. And that is also something to avoid when possible.
So, in other words: A) it is close to impossible to test the above code in meaningful ways. B) It would also be bad practice to do so (as envisioned in the question). Therefore the "best" solution here is to step back and re-design the whole thing. Yes, I am serious.
I am working on spring based project and writing unit test case using JUnit + Mockito. I am facing a problem while stubbing boolean value to a private method of same test class (after changing access level to public, still I have failed to stub the boolean value).
Below code snippet shows the simulation of same problem
class ABC {
public String method1(User userObj){
String result = "";
if(!isValidUser(userObj.getSessionID())){
return "InvalidUser";
} else {
// execute some logic
}
return result;
}
private boolean isValidUser(String sessionId) {
// Here it calls some other class to validate the user
if (sessionId == null || UserSessionPool.getInstance().getSessionUser(sessionId) == null) {
return false;
} else {
return true;
}
}
}
Here, I would like to write a test case for method1(). In class ABC I have a method called isValidUser() which helps to identify the user with in a session by looking into a global session pool which holds all logged-in used details i.e. UserSessionPool.getInstance().getSessionUser(sessionId).
While testing method1(), the moment test controller triggers isValidUser(userObj.getSessionID()) I would like to return true from isValidUser() method, so that I can continue to test rest of the implementation logic.
So far I have tried following ways using spy and mocked object to call the isValidUser() method and try to return true but nothing worked well.
Using PowerMockito
PowerMockito.doNothing().when(spyed_ABC_ClassObject, "isValidUser", true);
or
PowerMockito.doReturn(true).when(cntrl, "isValidUser", Mockito.anyString());
Using Whitebox
Whitebox.invokeMethod(spyed_ABC_ClassObject, "isValidUser", Mockito.anyString());
Using Mockito.when
when(spyed_ABC_ClassObject.isValidUser(Mockito.anyString())).thenReturn(true);
or
Mockito.doNothing().when(spyed_ABC_ClassObject).isValidUser(Mockito.anyString());
The other answer is: fix your design instead of turning to the big PowerMock hammer.
Yes, PowerMock allows you to mock static methods. But you should understand: static is an abnormality in good OO design. You only use it when you have very good reasons. As it leads to tight coupling between your classes, and surprise: it breaks your ability to write reasonable unit tests. Yes, PowerMock works; but sometimes, it does not. When your classes grow, and you do more and more things "statically", because, you know, PowerMock will do the job ... be prepared for bizarre fails at some point, that can take hours to hunt down; without ever finding real bugs in your production code.
So, consider an alternative:
Do not use static method calls. And if there is some static method around that you can't touch; consider building a small interface around that.
Instead: use dependency injection and simply pass objects implementing some interface into your production code. Because you can mock such objects without the need for PowerMock(ito).
In that sense: you simply created hard to test code. Now you intend to fix that using PowerMock. The other way (much more reasonable in my eyes) is to learn how to write testable code in the first place. Here is a good starting point for that.
Can you please try this out.
#Before
public void setUp() {
UserSessionPool mockConnectionPool = Mockito.mock(UserSessionPool.class);
}
#Test
public void testName() throws Exception {
//given
PowerMockito.mockStatic(UserSessionPool.class);
BDDMockito.given(UserSessionPool.getInstance()(...)).willReturn(mockConnectionPool);
Mockito.when(mockConnectionPool.getSessionUser(Mockito.anylong())).thenReturn(something);
//then
PowerMockito.verifyStatic();
}
Hope this helps. Happy coding !
I was trying to write unit test using jmocks and junit. (My Project uses core java- no frameworks-) I could not write unit test for some of my classes, by mocking external dependencies, when dependencies were initialized in a a no arg-constructor.
As i cannot provide the actual code, trying to explain the scenario by an example
public interface Apple {
String variety();
}
Implementation.
public class MalgovaApple implements Apple {
#Override
public String variety() {
return "Malgova";
}
}
Class to be tested
public class VarietyChecker {
private Apple apple;
VarietyChecker(){
this.apple = new MalgovaApple();
// instead of new, a factory method is used in actual application
}
public String printAppleVariety(){
String variety = apple.variety();
if(variety.length() < 3){
System.out.println("Donot use Code names- Use complete names");
return "bad";
}
return "good";
}
}
Junit test using jmock
public class VarietyCheckerUnitTest{
Mockery context = new JUnit4Mockery();
#Before
public void setUp() throws Exception {
}
#After
public void tearDown() throws Exception {
}
#Test
public void test_VarietyChecker() throws Exception{
final Apple mockapple = context.mock(Apple.class);
VarietyChecker printer = new VarietyChecker();
context.checking(new Expectations(){{
oneOf(mockapple).variety();will(returnValue("as"));
}});
String varietyNameValid = printer.printAppleVariety();
assertEquals("bad",varietyNameValid);
} }
This test fails - Mocking does not work the values "as" is not injected, the test class executes with MalgovaApple ...
Now if we add below constructor to VarietyChecker and use it test case - it gives expected output...
public VarietyChecker(Apple apple) {
super();
this.apple = apple;
}
and in unit test create test class object like
VarietyChecker printer = new VarietyChecker(mockapple);
Exposing a new constructor just for the purpose of testing is not a good idea. After all it is said that you should not alter the code for testing alone, more than that, i am afraid we have already written "some"(amount) code...
Am i missing something in junit or jmock that can make mocking work even incase of no-arg constructors. Or is this a limitation of simple junit and jmocks and should i migrate to something powerful like Jmockit /PowerMock
You should consider two choices.
Use a constructor parameter as you describe.
In this case, you're not "exposing a new constructor just for the purpose of testing". You're making your class more flexible by allowing callers to use a different factory implementation.
Don't mock it.
In this case, you are declaring that it never makes sense to use a different factory. Sometimes this is okay. At that point, the question changes, though. Instead of, "How do I mock this?" your question is now, "What am I gaining from writing this test?" You might not be gaining much of anything, and it might not make much sense to write the test at all.
If you don't mock it and decide a unit test is still worth it, then you should be asserting on other aspects of the code. Either an end state or some output. In this case, the factory call becomes an implementation detail that's not appropriate for mocking.
It's important not to fall for a "unit test everything" mentality. That is a recipe for Test-induced Design Damage. Evaluate your tests on a case by case basis, deciding whether they're providing you any real value or not. Not writing a unit test is a valid option and is even appropriate at times, even if it's option you try very hard to avoid.
Only you can make a determination which one makes the most sense in this case. From the the fact that this is a factory object we're talking about, I'd probably lean toward the former.
I'd like to use strict mocks, at least when developing for the first time some tests against old code, so any methods invoked on my mock will throw an exception if I didn't specifically define expectations.
From what I've come to see, Mockito if I didn't define any expectations will just return null, which will later on cause a NullPointerException in some other place.
Is it possible to do that? If yes, how?
What do you want it to do?
You can set it to RETURN_SMART_NULLS, which avoids the NPE and includes some useful info.
You could replace this with a custom implementation, for example, that throws an exception from its answer method:
#Test
public void test() {
Object mock = Mockito.mock(Object.class, new NullPointerExceptionAnswer());
String s = mock.toString(); // Breaks here, as intended.
assertEquals("", s);
}
class NullPointerExceptionAnswer<T> implements Answer<T> {
#Override
public T answer(InvocationOnMock invocation) throws Throwable {
throw new NullPointerException();
}
}
You could use verifyNoMoreInteractions. It's useful if the tested class catches exceptions.
#Test
public void testVerifyNoMoreInteractions() throws Exception {
final MyInterface mock = Mockito.mock(MyInterface.class);
new MyObject().doSomething(mock);
verifyNoMoreInteractions(mock); // throws exception
}
private static class MyObject {
public void doSomething(final MyInterface myInterface) {
try {
myInterface.doSomethingElse();
} catch (Exception e) {
// ignored
}
}
}
private static interface MyInterface {
void doSomethingElse();
}
Result:
org.mockito.exceptions.verification.NoInteractionsWanted:
No interactions wanted here:
-> at hu.palacsint.CatchTest.testVerifyNoMoreInteractions(CatchTest.java:18)
But found this interaction:
-> at hu.palacsint.CatchTest$MyObject.doSomething(CatchTest.java:24)
Actually, above is the only interaction with this mock.
at hu.palacsint.stackoverflow.y2013.q8003278.CatchTest.testVerifyNoMoreInteractions(CatchTest.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
...
Add this #Rule to your test class as a public field:
#RunWith(JUnitParamsRunner.class)
public class MyClassTests {
#Rule
public MockitoRule mockito = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
#Test
....
}
This value was added to Mockito in version 2.3.0
From the documentation:
Ensures clean tests, reduces test code duplication, improves
debuggability. Offers best combination of flexibility and
productivity. Highly recommended. Planned as default for Mockito v3.
Adds following behavior:
Improved productivity: the test fails early when code under test
invokes stubbed method with different arguments (see
PotentialStubbingProblem).
Cleaner tests without unnecessary
stubbings: the test fails when unused stubs are present (see
UnnecessaryStubbingException).
Cleaner, more DRY tests ("Don't Repeat
Yourself"): If you use Mockito.verifyNoMoreInteractions(Object...) you
no longer need to explicitly verify stubbed invocations. They are
automatically verified for you.
According to the source code of org.mockito.Mockito.RETURNS_DEFAULTS it selects its "what to do if no expectation" from a global setting.
Furthermore "If there is no global configuration then it uses {#link ReturnsEmptyValues} (returns zeros, empty collections, nulls, etc.)"
I have not yet been able to make that configuration.
In addition to the MockitoRule approach, if you don't need to use a specific test runner (and you are using Mockito 2.5.1 or higher), you could also consider using the MockitoJUnitRunner.StrictStubs runner, i.e.
#RunWith(MockitoJUnitRunner.StrictStubs.class)
(I would have commented on the post about MockitoRule, but don't have that ability yet)
Bellow Methods can verify no unexpected method called:
org.mockito.Mockito#only
org.mockito.Mockito#verifyNoMoreInteractions
I'm trying to implement unit testing for aproject, it uses a legacy "utility" project that is littered with static methods and many of the classes are final or their methods are final. I'm not able to update the legacy project at all.
JMock and EasyMock both choke on final methods, and I don't see a nice way to test the static calls. What techniques are there to test these?
If you're able to refactor your code, you can wrap your calls to the final/static methods in simple instance methods, for example:
protected Foo doBar(String name) {
return Utility.doBar(name);
}
This allows you to override your wrapper method in the unit test to return a mock instance of Foo.
Alternatively you can use Powermock, which extends Easymock (and Mockito) to allow mocking of final and static methods:
PowerMock is a framework that extend other mock libraries such as EasyMock with more powerful capabilities. PowerMock uses a custom classloader and bytecode manipulation to enable mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers and more.
Here's an example test mocking a static final method, the example shows how to mock some other types too:
#Test
public void testMockStaticFinal() throws Exception {
mockStatic(StaticService.class);
String expected = "Hello altered World";
expect(StaticService.sayFinal("hello")).andReturn("Hello altered World");
replay(StaticService.class);
String actual = StaticService.sayFinal("hello");
verify(StaticService.class);
assertEquals("Expected and actual did not match", expected, actual);
// Singleton still be mocked by now.
try {
StaticService.sayFinal("world");
fail("Should throw AssertionError!");
} catch (AssertionError e) {
assertEquals("\n Unexpected method call sayFinal(\"world\"):",
e.getMessage());
}
}
How about a level of indirection / Dependency Injection?
Since the legacy utility project is your dependency, create an interface to separate it out from your code. Now your real/production implementation of this interface delegates to the legacy utility methods.
public LegacyActions : ILegacyActions
{
public void SomeMethod() { // delegates to final/static legacy utility method }
}
For your tests, you can create a mock of this interface and avoid interacting with the legacy utility thingie.
JMockit allows you to mock static methods and final classes. I assume it uses some classloadin-fu, although I haven't really looked into it.
JMockit Expectations API allows
expectations to be set on any kind of
method invocation (on interfaces,
abstract classes, concrete final or
non final classes, and on static
methods), as well as on class
instantiation through any
constructors.
As already pointed out, JMockit can be used.
An example:
#Test
public void mockStaticAndFinalMethods(#Mocked LegacyService mock) {
new Expectations() {{
LegacyService.staticMethod("hello"); result = "Hello altered World";
}};
String actual = LegacyService.staticMethod("hello");
new LegacyService().finalMethod(123, "test");
assertEquals("Hello altered World", actual);
new Verifications() {{
mock.finalMethod(123, "test"); // verify this call occurred at least once
}};
}
If your non-refactorable method uses something like JNDI to connect to another service, I'd consider starting a JDNI service and populating it with stubs which you control. It's a pain but relatively straightforward. It may mean setting up a database or JMS listener or whatever but there should be a lightweight java implementation you can drop into the tests.
JMock together with JDave can mock final methods and classes, if you need to. Here
are instructions. That being said I would treat this legacy code (as others have suggested already) as an external dependency and build interfaces and mock those. It is another layer of indirection, but since you can't change that legacy code, it seems to be a reasonable one.