I'm having a situation in which I have certain mocking and utilities (not static methods, but certain manipulations relying on mocks).
Lets say like this,
class MyReusableClassForTesting {
#Mocked
private ClassA attribute;
// And some more #Mocked and methods that are relying on the mocks.
}
I want to use the instance of MyReusableClass in my test classes with mocks injected.
class MyTestClass {
// Need this be a real instance with mocks injected inside it
private MyReusableClassForTesting instance;
}
I tried with #Mocked, #Capturing, #Tested and #Injectable. None of them seem to work. Any idea, how can I make this work with Jmockit?
You would normally just do this:
class MyTestClass {
// Need this be a real instance with mocks injected inside it
#Tested
public MyReusableClassForTesting instance;
}
If the 'instance' constructor takes arguments, or if it has things Autowired, then add (possibly multiple) at the test-class level:
#Injectable
protected ClassA attribute;
To make sure JMockit is working, I usually add a simple test
#Test
public void testCtor() {
assertNotNull(instance);
}
JMockit will take care of creating the 'instance' based on #Tested and #Injectable. The only way this test fails is if JMockit isn't working - i.e. you forgot to add the javaagent. You generally need the javaagent in BOTH your build script (build.gradle or pom.xml) as well as when you run the test manually from your IDE.
Related
Let's suppose I have a test class A which extends from class B. This class A has one method with #BeforeClass annotation:
#BeforeClass
public static void setUp(){
createFakeData();
}
The method createFakeData() is in class B and its function is to create an object in database.
In order to do that, I have a bean in class B:
#Autowired
private DummyObjectsFactory dummyObjectsFactory;
And the content of the method createFakeData() could be something like that which returns a FakeData object:
public FakeData createFakeData() throws Exception
{
return dummyObjectsFactory.createFakeData();
}
The problem I'm facing is that the #BeforeClass method has to be static, that means that the createFakeData method has to be static too. But I cannot set that method to static because my bean dummyObjectsFactory will be always null.
How can I make my createFakeData method static avoiding my dummyObjectsFactory bean to be not null?
As far as I know, that is not permitted in JUnit. However you can do some things for arrange it.
First, you can use TestNG, which allows to do exactly what you want.
If that is not an option, instead of using #BefloreClass annotation, you can use #Before. The difference between both is that #BeforeClass executes the method before all the tests while #Before executes the method before each test. If you use #Before, I would annotate the class with #Transactional in order to delete the data saved in the database.
In the end, if you don't want to execute the method for each test, you can use #Before and flat the call:
#Before
public void init(){
if(!fakeDataCalled){
createFakeData();
fakeDataCalled=true;
}
}
I believe you want to annotate your test class (B) with #RunWith(SpringRunner.class) so that the autowiring happens correctly.
Take a look at section 15.4.4 in the Spring Reference.
You can also just browse to that page and search for "RunWith"
Caveats:
I don't like static methods. They tend to make unit testing difficult.
I don't like extending tests to make other tests. I find it easier to make each test standalone and use composition for any shared functionality (i.e. make utility classes for shared test functionality that reside in the test source tree).
I don't like my unit tests depending on autowiring. I mock all the dependencies and inject them with either reflection or the #InjectMocks annotation.
Is it possible to both mock an abstract class and inject it with mocked classes using Mockito annotations. I now have the following situation:
#Mock private MockClassA mockClassA;
#Mock private MockClassB mockClassB;
#Mock(answer = Answers.CALLS_REAL_METHODS) private AbstractClassUnderTest abstractClassUnderTest;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
Whitebox.setInternalState(abstractClassUnderTest, mockClassA);
Whitebox.setInternalState(abstractClassUnderTest, mockClassB);
}
I'd like to use something like #InjectMocks on AbstractClassUnderTest but it can't be used in combination with #Mock. The current situation, with Whitebox from Powermock, works but I'm curious if it's possible to solve it with just annotations. I couldn't find any solutions or examples.
(I know about the objections to test abstract classes and I'd personally rather test a concrete implementation and just use #InjectMocks.)
I am not aware of any way to go about this, for one clear reason: #InjectMocks is meant for non-mocked systems under test, and #Mock is meant for mocked collaborators, and Mockito is not designed for any class to fill both those roles in the same test.
Bear in mind that your #Mock(CALLS_REAL_METHODS) declaration is inherently dangerous: You're testing your AbstractClassUnderTest, but you are not running any constructors or initializing any fields. I don't think you can expect a test with this design to be realistic or robust, no matter what annotations can or cannot do for you. (Personally, I was previously in favor of real partial mocks of abstract classes as a "tool in the toolbox", but I'm coming around to thinking they're too far removed from reality to be useful.)
Were I in your position, I would create a small override implementation for testing:
#RunWith(JUnit4.class) public class AbstractClassTest {
/** Minimial AbstractClass implementation for testing. */
public static class SimpleConcreteClass extends AbstractClass {
public SimpleConcreteClass() { super("foo", "bar", 42); }
#Override public void abstractMethod1() {}
#Override public String abstractMethod2(int parameter) { return ""; }
}
#InjectMocks SimpleConcreteClass classUnderTest;
#Mock mockClassA;
#Mock mockClassB;
}
At this point, you have a simple and predictable AbstractClass implementation, which you can use even without a mocking framework if you just wanted to test that AbstractClass has the same API for extension that it did before. (This is an often-overlooked test for abstract classes.) You can even extract this, as it may be useful for other testing: Should you want to override the abstract behavior for a single test class, you can create an anonymous inner class with just a single method override, or you can set classUnderTest = spy(classUnderTest); to set up Mockito proxying and the behavior you want.
(Bear in mind that #InjectMocks and #Spy can't be used reliably together, as documented in this GitHub issue and the Google Code and mailing list threads to which it links.)
I found some trick with mocking field before initialization.
#InjectMocks
private AbstractClass abstractClass;
#Mock
private MockClass mockClass;
#Before
public void init() {
abstractClass= mock(AbstractClass.class, Answers.CALLS_REAL_METHODS);
MockitoAnnotations.initMocks(this);
}
Maybe it'll help someone.
How can you get a mock object in at runtime when it is not created/initialized in the class you are testing, it is not static (singleton pattern), or you don't have some sort of test constructor to hook into?
In a class that I am writing some unit testing for, I have come across a scenario I haven't encountered/solved yet. I have a JMS resource (a QueueConnectionFactory for reference, but it shouldn't matter), that is a private variable of the class I am testing. Since it has the javax.annotation.Resource annotation, at runtime it is assumed to be available. During testing, it is not, which creates the need for mocking this object.
It is not a static class and is not being used in a static way, if it was I could easily mock using the various static mocking methods I have run into. Since the resource is never created locally (in a constructor or even in a test constructor), I have no way of passing in a Mock object so that at runtime of the test, the mock is used instead of the actual object. How can I mock this Resource so that when the test executes, it will be used in place of the private #Resource object in the class I am testing?
For reference, the code is calling createConnection() on the QueueConnectionFactory which is throwing a null pointer exception since the Factory has not been initialized/mocked.
#Stateless
public class Example{
#Resource(name = "jms/exampleQCF")
private QueueConnectionFactory queueFactory;
...
public void testMe(){
Connection connection = queueFactory.createConnection();
...
}
}
After a lot more hunting around and looking at all the options Mockito/Powermock had to offer, I found the solution (which I will share in case others run into this same issue).
When you have private member variables that are never initialized (and just assumed created in other places), you can use the #InjectMocks annotation to "inject" Mocks you want into your class you are testing.
Add a variable in your test class for the class you are testing, and give it the annotation #InjectMocks (org.Mockito.InjectMocks).
Use #Mock annotations to setup the mocks you want to inject. Use the #Mock (name = "privateVariableNameHere") name property to map the Mock object to the private variable inside your class you are testing.
In either a setup function or before you call your class, initialize the mocks. The easiest way I have found is to use a "setup" method with the #Before annotation. Then inside there call MockitoAnnotations.initMocks(this); to quickly initialize anything with the #Mock annotation.
Define your Mock functionality in your test method (before calling the method you are testing).
Using the #InjectMock object, call your method you are testing... the mocks SHOULD be hooked in and working as defined in the earlier steps.
So for the example class I use above, the code to test/mock would have Connection returned as a mock which you can do whatever with. Based on the example above in my question, this is what the code would look like:
#RunWith(PowerMockRunner.class)
#PrepareForTest({/* Static Classes I am Mocking */})
public class ExampleTest {
#Mock (name = "queueFactory") //same name as private var.
QueueConnectionFactory queueFactoryMock;
#Mock
Connection connectionMock; //the object we want returned
#InjectMocks
Example exampleTester; //the class to test
#Before
public void setup(){
MockitoAnnotations.initMocks(this); // initialize all the #Mock objects
// Setup other Static Mocks
}
#Test
public void testTestMe(){
//Mock your objects like other "normally" mocked objects
PowerMockito.when(queueFactoryMock.createConnection()).thenReturn(connectionMock);
//...Mock ConnectionMock functionality...
exampleTester.testMe();
}
}
Several approaches here:
ReflectionTestUtils of Spring Testing framework: ReflectionTestUtils.setField(objectToTest, "privateFieldName", mockObjectToInject);. With this you don't introduce another dependency.
org.mockito.internal.util.reflection.FieldSetter.
PowerMock.Whitebox.setInternalState() to mock a private field.
If you need to mock internal local variable creation, use PowerMockito.whenNew(Foo.class).withNoArguments().thenReturn(foo);. Very, very useful. Cannot find other ways to do the same.
With only Mockito you cannot mock local variable creation, because when(any(Foo.class) does not work; will return null. It compiles but does not work.
References:
Mockito: Mock private field initialization
I'm trying to unit test a class (let's say, "ClassUnderTest") and its use of a particular library class (let's call it "Helper"). So I'm injecting a mocked Helper into the ClassUnderTest and using Expectations to check things out.
public class TestUseOfHelper {
#Autowired ClassUnderTest classUnderTest;
#Mocked HelperClass helper;
[...]
#Before
public void setUp() throws Exception {
Deencapsulation.setField(classUnderTest, "helper", helper);
}
[...]
#Test
public void test() {
new Expectations() {{
helper.doSomething(any);
}};
classUnderTest.useHelper();
}
So far, so good.
In other tests (same package, different file), I'm testing other aspects of the ClassUnderTest where I just want Helper to do its thing.
public class TestOtherQualities {
#Autowired ClassUnderTest classUnderTest;
[...]
#Test
public void test() {
result = classUnderTest.processSomething();
assertNonNull(result);
}
Those tests work fine as well.
The problem comes in when I run the suite of tests. Now, the second set fails, apparently because the Mocked Helper is still in place!
I assume that the full suite is being executed in the same JVM and that Spring has created one ClassUnderTest, injects the mock like it's told, but then just reuses the same ClassUnderTest object for the next test. How do I keep them separate? How can I get "fresh" objects for each separate test file? What am I not getting/googling?
I've tried numerous variations of defining objects within the Expectations blocks and using #Tested/#Injected but with no luck. BTW, I'm avoiding mocking the Helper in other tests because I need it to do its thing. Also ClassUnderTest autowires a bunch of other objects, which in turn autowire still others, so mocking everything that ClassUnderTest references is impractical.
Any insights, Oh knowledgeable Stack Overflow Magic 8 Ball? ("Try Later" is not acceptable.)
Annotate the test class with
#DirtiesContext(classMode = AFTER_CLASS)
if you want to reset the app context between test classes.
It's a unit test. So you shouldn't use Spring at all to create and autowire the objects. Just create a new ClassUnderTest every time you need one, and inject the mock dependencies manually :
#Before
public void setUp() {
this.classUnderTest = new ClassUnderTest();
Deencapsulation.setField(classUnderTest, "helper", mockHelper);
}
Note: I don't know JMockit, and it might have annotations that even create a new and inject mock dependencies automatically. The point of my answer is that Spring should be out of the picture for unit tests. That's the main advantage of dependency injection: being able to create instances of objects to test, and being able to manually inject mock dependencies.
We are writing JUnit tests for a class that uses Spring autowiring to inject a dependency which is some instance of an interface. Since the class under test never explicitly instantiates the dependency or has it passed in a constructor, it appears that JMockit doesn't feel obligated to instantiate it either.
Up until now we have been using SpringRunner to have Spring load mock dependencies for us, which works. Two things we don't like about this are 1) the Spring framework has to be loaded and initialized each time running the tests which is not exactly speedy, and 2) we are forced to explicitly create all mock dependencies as real classes, something which JMockit helps eliminate.
Here's a simplified example of what we're testing:
public class UnitUnderTest {
#Autowired
ISomeInterface someInterface;
public void callInterfaceMethod() {
System.out.println( "UnitUnderTest.callInterfaceMethod calling someInterface.doSomething");
someInterface.doSomething();
}
}
So, the question is, is there a way to have JMockit create a mock someInterface?
JMockit will always instantiate a mocked interface (except in the case of a final mock field), but that only occurs in test code. It will not automatically inject the instance into code under test.
You would have to manually inject the mock instance. For example:
public class SomeTest
{
#Autowired UnitUnderTest unitUnderTest;
#Mocked ISomeInterface theMock; // created and assigned automatically
#Test
public void testSomeMethod()
{
Deencapsulation.setField(unitUnderTest, theMock);
//proceed with unit test here
}
}
mockit.Deencapsulation is a Reflection-based utility class that lets you invoke private methods, get/set fields, etc.
You can use org.springframework.test.util.ReflectionTestUtils to explicitly inject your mocked ISomeInterface in your test case.
See documentation
With the hints kindly provided above, here's what I found most useful as someone pretty new to JMockit: JMockit provides the Deencapsulation class to allow you to set the values of private dependent fields (no need to drag the Spring libraries in), and the MockUp class that allows you to explicitly create an implementation of an interface and mock one or more methods of the interface. Here's how I ended up solving this particular case:
#Before
public void setUp() {
IMarketMakerDal theMock = new MockUp <IMarketMakerDal>() {
#Mock
MarketMakerDcl findByMarketMakerGuid( String marketMakerGuid ) {
MarketMakerDcl marketMakerDcl = new MarketMakerDcl();
marketMakerDcl.setBaseCurrencyCode( CURRENCY_CODE_US_DOLLAR );
return marketMakerDcl;
}
}.getMockInstance();
setField( unitUnderTest, theMock );
}
Thanks everyone for the help.
For those people who met
java.lang.IllegalStateException: Missing #Injectable for field ***
or
java.lang.IllegalStateException: Missing #Tested class for field ***
error when using jmockit to mock #autowired field in spring ( or spring boot) framework, I did below two steps to avoid above errors:
use #Tested(fullyInitialized=true) instead of #Tested
https://groups.google.com/forum/#!msg/jmockit-users/uo0S51lSX24/lQhLNN--eJcJ
revert jmockit's version back to 1.18 or previous ones
https://groups.google.com/forum/#!topic/jmockit-users/wMFZggsA8LM
If you have a #Qualifier annotation for the interface, you need to name your #Injectable field exactly as it is named in qualifier.
Here is quote from JMockit doc:
Custom names specified in field annotations from Java EE (#Resource(name), #Named) or the Spring framework (#Qualifier) are used when looking for a matching #Injectable or #Tested value. When such a name contains a - (dash) or . (dot) character, the corresponding camel-cased name is used instead.
For example:
#Component
public class AClass {
#Autowired
private Bean1 bean1;
#Autowired
#Qualifier("my-dashed-name")
private AmqpTemplate rpcTemplate;
}
Unit test class:
public class AClassTest {
#Injectable
private Bean1 bean1;
#Injectable
private AmqpTemplate myDashedName;
#Tested
private AClass aClass = new AClass();
}
Also there is no need to use setFiled for each #Autowired bean, all fields injects automatically when #Tested class instantiated. Tested on JMockit ver. 1.30