When should we use Mockery vs JUnit4Mockery? - junit

If writing a Java unit test with mocking using JMock, should we use
Mockery context = new Mockery()
or
Mockery context = new JUnit4Mockery()
What is the difference between the two, and when should we use which?

#Rhys It's not the JUnit4Mockery that replaces the need to call assertIsSatisfied, its the JMock.class (combined with the #RunWith). You wont need to call assertIsSatisfied when you create a regular Mockery.
The JUnit4Mockery translates errors.
By default, expectation exceptions are reported in Junit as ExpectationError, so for example, using
Mockery context = new Mockery();
you'll get
unexpected invocation: bar.bar()
no expectations specified: did you...
- forget to start an expectation with a cardinality clause?
- call a mocked method to specify the parameter of an expectation?
and using,
Mockery context = new JUnit4Mockery();
you'll get
java.lang.AssertionError: unexpected invocation: bar.bar()
no expectations specified: did you...
- forget to start an expectation with a cardinality clause?
- call a mocked method to specify the parameter of an expectation?
what happened before this: nothing!
The JUnit4Mockery converted the ExpectationError to an java.lang.AssertionError which JUnit deals with. Net result is that it'll show up in your JUnit report as an failure (using JUnit4Mockery) rather than an error.

When using JMock with JUnit 4, you can avoid some boilerplate code by taking advantage of the JMock test runner. When you do this, you must use the JUnit4Mockery instead of the regular Mockery.
Here is how you'd structure a JUnit 4 test:
#RunWith(JMock.class)
public void SomeTest() {
Mockery context = new JUnit4Mockery();
}
The main advantage is there is no need to call assertIsSatisfied in each test, it is called automatically after each test.

Better yet, per http://incubator.apache.org/isis/core/testsupport/apidocs/org/jmock/integration/junit4/JUnitRuleMockery.html use #Rule and avoid #RunWith which you might need for some other system:
public class ATestWithSatisfiedExpectations {
#Rule
public final JUnitRuleMockery context = new JUnitRuleMockery();
private final Runnable runnable = context.mock(Runnable.class);
#Test
public void doesSatisfyExpectations() {
context.checking(new Expectations() {
{
oneOf(runnable).run();
}
});
runnable.run();
}
}

Related

Junit for Solr Indexing Documents from AEM

I have my ServiveImpl class, which has public methods to create and delete index from AEM to Solr. How can we handle the Junit for these void methods using Mockito? Any pointers will be help. Mainly for testing integration with Solr
In this case, your JUnit wouldn't really make any difference other than giving you some test coverage.
The reason behind writing a Junit is to ensure that a method returns a result, or throws an exception. With a void method, the only thing that can be tested is that the method executes.
To solve this, it would be good to at least return a boolean value. Without this, you can never be sure whether the index was really deleted or not.
So the suggestion here would be-
Update the method to ensure the correct error handling takes place.
Based on the method execution, return a boolean value at least. This will not have any impact on your project because the method was void anyway and no calls would be impacted.
In your Junit, assert the returned value as true or false, or just use the assertTrue method.
boolean deleteIndex(String indexName) {
if (deleted) {
return true;
} else {
return false;
}
}
JUnit-
#InjectMocks
private ServiveImpl service = new ServiveImpl();
#Test
public void testIndexDeletion() {
boolean indexDeleted = ServiveImpl.deleteIndex("someIndex");
assertTrue(indexDeleted);
}

Unable to mock the local variable inside a method in java [duplicate]

I'm using Mockito 1.9.0. I want mock the behaviour for a single method of a class in a JUnit test, so I have
final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);
The problem is, in the second line, myClassSpy.method1() is actually getting called, resulting in an exception. The only reason I'm using mocks is so that later, whenever myClassSpy.method1() is called, the real method won't be called and the myResults object will be returned.
MyClass is an interface and myInstance is an implementation of that, if that matters.
What do I need to do to correct this spying behaviour?
Let me quote the official documentation:
Important gotcha on spying real objects!
Sometimes it's impossible to use when(Object) for stubbing spies. Example:
List list = new LinkedList();
List spy = spy(list);
// Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
// You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
In your case it goes something like:
doReturn(resultsIWant).when(myClassSpy).method1();
In my case, using Mockito 2.0, I had to change all the any() parameters to nullable() in order to stub the real call.
My case was different from the accepted answer. I was trying to mock a package-private method for an instance that did not live in that package
package common;
public class Animal {
void packageProtected();
}
package instances;
class Dog extends Animal { }
and the test classes
package common;
public abstract class AnimalTest<T extends Animal> {
#Before
setup(){
doNothing().when(getInstance()).packageProtected();
}
abstract T getInstance();
}
package instances;
class DogTest extends AnimalTest<Dog> {
Dog getInstance(){
return spy(new Dog());
}
#Test
public void myTest(){}
}
The compilation is correct, but when it tries to setup the test, it invokes the real method instead.
Declaring the method protected or public fixes the issue, tho it's not a clean solution.
The answer by Tomasz Nurkiewicz appears not to tell the whole story!
NB Mockito version: 1.10.19.
I am very much a Mockito newb, so can't explain the following behaviour: if there's an expert out there who can improve this answer, please feel free.
The method in question here, getContentStringValue, is NOT final and NOT static.
This line does call the original method getContentStringValue:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), isA( ScoreDoc.class ));
This line does not call the original method getContentStringValue:
doReturn( "dummy" ).when( im ).getContentStringValue( anyInt(), any( ScoreDoc.class ));
For reasons which I can't answer, using isA() causes the intended (?) "do not call method" behaviour of doReturn to fail.
Let's look at the method signatures involved here: they are both static methods of Matchers. Both are said by the Javadoc to return null, which is a little difficult to get your head around in itself. Presumably the Class object passed as the parameter is examined but the result either never calculated or discarded. Given that null can stand for any class and that you are hoping for the mocked method not to be called, couldn't the signatures of isA( ... ) and any( ... ) just return null rather than a generic parameter* <T>?
Anyway:
public static <T> T isA(java.lang.Class<T> clazz)
public static <T> T any(java.lang.Class<T> clazz)
The API documentation does not give any clue about this. It also seems to say the need for such "do not call method" behaviour is "very rare". Personally I use this technique all the time: typically I find that mocking involves a few lines which "set the scene" ... followed by calling a method which then "plays out" the scene in the mock context which you have staged... and while you are setting up the scenery and the props the last thing you want is for the actors to enter stage left and start acting their hearts out...
But this is way beyond my pay grade... I invite explanations from any passing Mockito high priests...
* is "generic parameter" the right term?
One more possible scenario which may causing issues with spies is when you're testing spring beans (with spring test framework) or some other framework that is proxing your objects during test.
Example
#Autowired
private MonitoringDocumentsRepository repository
void test(){
repository = Mockito.spy(repository)
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
In above code both Spring and Mockito will try to proxy your MonitoringDocumentsRepository object, but Spring will be first, which will cause real call of findMonitoringDocuments method. If we debug our code just after putting a spy on repository object it will look like this inside debugger:
repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$
#SpyBean to the rescue
If instead #Autowired annotation we use #SpyBean annotation, we will solve above problem, the SpyBean annotation will also inject repository object but it will be firstly proxied by Mockito and will look like this inside debugger
repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$
and here is the code:
#SpyBean
private MonitoringDocumentsRepository repository
void test(){
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
Important gotcha on spying real objects
When stubbing a method using spies , please use doReturn() family of methods.
when(Object) would result in calling the actual method that can throw exceptions.
List spy = spy(new LinkedList());
//Incorrect , spy.get() will throw IndexOutOfBoundsException
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
I've found yet another reason for spy to call the original method.
Someone had the idea to mock a final class, and found about MockMaker:
As this works differently to our current mechanism and this one has different limitations and as we want to gather experience and user feedback, this feature had to be explicitly activated to be available ; it can be done via the mockito extension mechanism by creating the file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker containing a single line: mock-maker-inline
Source: https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2#mock-the-unmockable-opt-in-mocking-of-final-classesmethods
After I merged and brought that file to my machine, my tests failed.
I just had to remove the line (or the file), and spy() worked.
One way to make sure a method from a class is not called is to override the method with a dummy.
WebFormCreatorActivity activity = spy(new WebFormCreatorActivity(clientFactory) {//spy(new WebFormCreatorActivity(clientFactory));
#Override
public void select(TreeItem i) {
log.debug("SELECT");
};
});
As mentioned in some of the comments, my method was "static" (though being called on by an instance of the class)
public class A {
static void myMethod() {...}
}
A instance = spy(new A());
verify(instance).myMethod(); // still calls the original method because it's static
Work around was make an instance method or upgrade Mockito to a newer version with some config: https://stackoverflow.com/a/62860455/32453
Bit late to the party but above solutions did not work for me , so sharing my 0.02$
Mokcito version: 1.10.19
MyClass.java
private int handleAction(List<String> argList, String action)
Test.java
MyClass spy = PowerMockito.spy(new MyClass());
Following did NOT work for me (actual method was being called):
1.
doReturn(0).when(spy , "handleAction", ListUtils.EMPTY_LIST, new String());
2.
doReturn(0).when(spy , "handleAction", any(), anyString());
3.
doReturn(0).when(spy , "handleAction", null, null);
Following WORKED:
doReturn(0).when(spy , "handleAction", any(List.class), anyString());

Why I can verify static method for 20 times and it doesn't fail?

That's my test code:
public void testApplyListWhenAddTheSameIDThenReturnDuplicateEntityException(){
MyEntity entityRCM = createMyEntity(AGE_ID, WEIGHT_ID, 0L);
entityModel.addEntity(entityRCM);
MyEntity entityOPC = createMyEntity(DIFF_AGE_ID, WEIGHT_ID, 0L);
EntityCreate create = new EntityCreate(entityOPC);
List<EntityChange> changeList = new ArrayList<EntityChange>();
changeList.add(create);
try {
entityModel.apply(changeList);
fail();
}catch(DuplicateEntityException e) {
PowerMockito.verifyStatic(times(20));
LogManager.error(Mockito.<Logger>anyObject(),Mockito.anyString(),Mockito.<DuplicateEntityException>anyObject());
}
}
The problem is here:
PowerMockito.verifyStatic(times(20));
LogManager.error(Mockito.<Logger>anyObject(),Mockito.anyString(),Mockito.<DuplicateEntityException>anyObject());
I want to verify a static method error in class LogManager, but how can I verify this method for twenty times but it doesn't fail.
Solved in the comments:
Did you add #PrepareForTest and mockStatic? If not, then you may have set up your matchers and static call but PowerMock never sees the actual call to mock before your test completes.
For context, PowerMock mocks static classes by intercepting the classloader and loading a replacement class that calls PowerMock-provided implementations instead of the originals. Unless you add the right preparation, PowerMock won't replace the class, so it won't count static method calls or identify the method to verify, and the test will complete before the verification call ever actually happens.

Spock mock returns null inside collabolator but not in feature method

I have a problem with Spock Mock() object.
I have a java class I'm trying to test. This class does some ftp stuff I want to mock.
My sample code
class ReceiveDataTest extends Specification{
String downloadPath = 'downloadPath';
String downloadRegex = 'downloadRegex';
SftpUtils sftpUtils = Mock();
ReceiveData receiveData;
def setup(){
sftpUtils.getFileNames(downloadPath,downloadRegex) >> ['file1', 'file2']
receiveData= new ReceiveData()
receiveData.setDownloadPath(downloadPath)
receiveData.setDownloadRegex(downloadRegex)
receiveData.setSftpUtils(sftpUtils);
}
def "test execute"() {
given:
def files = sftpUtils.getFileNames(downloadPath,downloadRegex)
files.each{println it}
when:
receiveData.execute();
then:
1*sftpUtils.getFileNames(downloadPath,downloadRegex)
}
}
public class ReceiveData(){
//fields, setters etc
public void execute() {
List<String> fileNames = sftpUtils.getFileNames(downloadPath, downloadRegex);
for (String name : fileNames) {
//dowload and process logic
}
}
}
Now, inside "test execute" the files.each{} prints what is expected. But when receiveData.execute() is called my sftpUtils are returning null..
Any ideas why?
EDIT
Maybe i didnt state my problem well - that I dont want to just check if getFileNames was called. I need the result to proper check the for loop. If I comment the loop inside execute, the test passes. But since I use the result of the getFilenames() method, I get a NPE execute method reaches the for loop. With mockito I would do something like this
Mockito.when(sftpUtils.getFilenames(downloadPath, downloadRegex)).thenReturn(filenamesList);
receiveData.execute();
Mockito.verify(sftpUtils).getFilenames(downloadPath, downloadRegex);
//this is what I want to test and resides inside for loop
Mockito.verify(sftpUtils).download(downloadPath, filenamesList.get(0));
Mockito.verify(sftpUtils).delete(downloadPath, filenamesList.get(0));
but I cannot use Mockito.verify() inside Spock then block
The main problem is that you did not include the response generator (the >> part) in the expectation (i.e. the "1 * ..." part inside the then: block).
This is explained well in the spock documentation.
http://spockframework.org/spock/docs/1.0/interaction_based_testing.html#_combining_mocking_and_stubbing
https://spock-framework.readthedocs.org/en/latest/interaction_based_testing.html#wheretodeclareinteractions
You shouldn't have to declare your stub in the setup: block. You can just specifiy it once in the then: block -- even though that follows the call to receiveData.execute(). That's part of the magic of spock thanks to Groovy AST transformations. And since (non-shared) fields are reinitialized before each test (more AST based magic), you don't even need setup() in this case.
Another odd thing is that you are both stubbing out sftpUtils.getFilenames() and also calling it from the test code. Mocks and stubs are intended to replace collaborators that are called from the system under test. There's no reason to call the stub from the test driver. So delete the call to getFilenames() from your given block and let the code under test call it instead (as it does).
Groovy lets you simplify calls to Java set and get methods. Look at the initialization of receiveData below. Its okay to use def in Groovy. Let the compiler figure out the data types for you.
Leading to something like:
class ReceiveDataTest extends Specification {
// only use static for constants with spock
static String PATH = 'downloadPath'
static String REGEX = 'downloadRegex'
def mockSftpUtils = Mock(SftpUtils)
def receiveData = new ReceiveData(downloadPath : PATH,
downloadRegex : REGEX,
sftpUtils : mockSftpUtils)
def "execute() calls getFileNames() exactly once"() {
when:
receiveData.execute()
then:
1 * mockSftpUtils.getFileNames(PATH, REGEX) >> ['file1', 'file2']
0 * mockSftpUtils.getFileNames(_,_)
// The second line asserts that getFileNames() is never called
// with any arguments other than PATH and REGEX, aka strict mocking
// Order matters! If you swap the lines, the more specific rule would never match
}
}

How can I make my JUnit tests run in random order?

I have the classical structure for tests, I have a test suite of different suites like DatabaseTests, UnitTests etc. Sometimes those suites contains other suites like SlowDatabaseTests, FastDatabaseTests etc.
What I want is to randomize the running order of tests so I will make sure they are not dependent to each other. Randomization should be at every level, like suite should shuffle test class order, and test class should shuffle test method order.
If it is possible to do this in Eclipse that will be the best.
You do have a Sortable but I can't see how you would use it.
You could extend BlockJUnit4ClassRunner and have computeTestMethods() return a randomized copy of super.computeTestMethods(). Then use the #RunWith to set that as the runner to use.
e.g.
package com.stackoverflow.mlk;
import java.util.Collections;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;
public class RandomBlockJUnit4ClassRunner extends BlockJUnit4ClassRunner {
public RandomBlockJUnit4ClassRunner(Class<?> klass)
throws InitializationError {
super(klass);
}
protected java.util.List<org.junit.runners.model.FrameworkMethod> computeTestMethods() {
java.util.List<org.junit.runners.model.FrameworkMethod> methods = super.computeTestMethods();
Collections.shuffle(methods);
return methods;
}
}
Then
#RunWith(com.stackoverflow.mlk.RandomBlockJUnit4ClassRunner.class)
public class RandomOrder {
#Test
public void one() {
}
#Test
public void two() {
}
#Test
public void three() {
}
}
https://github.com/KentBeck/junit/pull/386 introduces some orders but not RANDOM. Probably you do not really want this; tests should run deterministically. If you need to verify that different permutations of tests still pass, either test all permutations; or, if this would be impractically slow, introduce a “random” seed for shuffling that is determined by an environment variable or the like, so that you can reproduce any failures. http://hg.netbeans.org/main/file/66d9fb12e98f/nbjunit/src/org/netbeans/junit/MethodOrder.java gives an example of doing this for JUnit 3.
In general what you need to do is to write your own test runner and in the test runner class aggregate the methods and randomly run each test (make sure you don't run a test twice).
Read more about the test framework and how to write your own test runner here:
http://www.ddj.com/architect/184415674
In JUnit 4.13, to run the tests within a test class in random order, write a small helper class:
import org.junit.runner.manipulation.Ordering;
import java.util.Random;
public class RandomOrder implements Ordering.Factory {
#Override
public Ordering create(Ordering.Context context) {
long seed = new Random().nextLong();
System.out.println("RandomOrder: seed = " + seed);
return Ordering.shuffledBy(new Random(seed));
}
}
Then, annotate your test class with:
#OrderWith(RandomOrder.class)
This way, the test methods of this one class are run in random order. Plus, if they unexpectedly fail, you know the random seed to repeat exactly this order.
I don't know though how to configure this for a whole project or a test suite.
I will make sure they are not dependent to
each other
You should make sure that this is the case without relying on random execution order. What makes you fear that dependencies may exist?
This issue is open on JUnit GitHub since 2 years, and point out 2 independent issues:
- Tests depending on the execution order;
- Non repeatable tests.
Consider adressing the issue at the root, rather than trying to use the framework to do the job afterwards. Use setUp and tearDown method to guarantee isolation, and test at the smallest level.
Here is a solution with Gradle and JUnit 5.8.0
Step 1 : Ensure that you have latest JUnit version dependency.
Step 2 : Define the required properties under build.gradle test section
test {
useJUnitPlatform()
systemProperties([
//Random in method level
'junit.jupiter.testmethod.order.default': 'org.junit.jupiter.api.MethodOrderer$Random',
// Random in class level
'junit.jupiter.testclass.order.default' : 'org.junit.jupiter.api.ClassOrderer$Random',
// Log configuration to see the seed
'java.util.logging.config.file' : file('src/test/resources/logging.properties')
])
//To print the JUnit logs in console
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
}
}
Step 3: Define logging.properties under src/test/resources
.level=CONFIG
java.util.logging.ConsoleHandler.level=CONFIG
org.junit.jupiter.api.ClassOrderer$Random.handlers=java.util.logging.ConsoleHandler
org.junit.jupiter.api.MethodOrderer$Random.handlers=java.util.logging.ConsoleHandler
Step 4 : Run test. gradlew clean test
You can see the seed used for the random test in the console
CONFIG: ClassOrderer.Random default seed: 65423695211256721
CONFIG: MethodOrderer.Random default seed: 6542369521653287
In case of flaky test, you can reproduce it by configuring the same seed where the JUnit tests were failing
systemProperties([
'junit.jupiter.execution.class.order.random.seed' : '65423695211256721'
'junit.jupiter.execution.order.random.seed' : '6542369521653287'
])
References : how-to-randomize-tests-in-junit , Random