I have a class, say SimpleClass, that has two functions with the same name and the same number of parameters but different parameter types. Now I assume mocking their return values should be as using two when statements with the appropriate matchers but instead when I attempt that I get the following error:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Misplaced argument matcher detected here:
-> at mocks.MockTest.whenMethodsHaveSimilarSignatures(MockTest.java:28)
-> at mocks.MockTest.whenMethodsHaveSimilarSignatures(MockTest.java:28)
Here's a sample of what I'm attempting:
public class SimpleClass {
public boolean doWork(String value, String name) {
return false;
}
public boolean doWork(Integer value, String name) {
return true;
}
}
#RunWith(MockitoJUnitRunner.class)
public class MockTest {
private SimpleClass thing;
#Before
public void setup() {
thing = new SimpleClass();
}
#Test
public void whenMethodsHaveSimilarSignatures() {
when(thing.doWork(anyString(), anyString())).thenReturn(true);
when(thing.doWork(any(Integer.class), anyString())).thenReturn(false);
assertThat(thing.doWork("one", "name")).isTrue();
assertThat(thing.doWork(1, "name")).isFalse();
}
}
While I'm not a wizard at Mockito I've been using it for a while and never encountered this issue. Thoughts? I'm using Mockito-Core v2.2.9
You should not use any(Object.class) while stubbing overloaded methods because both String and Integer are child classes of Object, so specify the particular arguments during stubbing.You can also use ArgumentMatchers
when(thing.doWork(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenReturn(true);
when(thing.doWork(ArgumentMatchers.any(Integer.class), anyString())).thenReturn(false);
And also you are not mocking the SimpleClass
#RunWith(MockitoJUnitRunner.class)
public class MockTest {
private SimpleClass thing = Mockito.mock(SimpleClass.Class);
#Before
public void setup() {
MockitoAnnotations.initMocks(this); // need to enable these annotations programmatically
}
#Test
public void whenMethodsHaveSimilarSignatures() {
when(thing.doWork(anyString(), anyString())).thenReturn(true);
when(thing.doWork(any(Integer.class), anyString())).thenReturn(false);
//or
when(thing.doWork(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenReturn(true);
when(thing.doWork(ArgumentMatchers.any(Integer.class), anyString())).thenReturn(false);
assertThat(thing.doWork("one", "name")).isTrue();
assertThat(thing.doWork(1, "name")).isFalse();
}
}
Related
I am trying to write unit test cases for one of the methods in code.Below is the method
public boolean isValid() {
if(object == null)
return false
//do something here and return value.
}
The object is created by this method which is done before without getter setter method.
private Object returnObject() {
object = Axis2ConfigurationContextFactory.getConfigurationContext();
return object;
}
When I try to test isValid(), the object is always null, so it never goes in the code to do something.
I was checking if there is any way to skip that line or make the object not null. I also tried creating an object using returnObject method. But it uses Axis library classes which throws error if it does not find certain data. What can be done in this case? I am dealing with legacy code so any pointers would be helpful.
Edit : Adding test implementation.
#PowerMockIgnore({ "javax.xml.*", "org.w3c.dom.*", "javax.management.*" })
public class ClassTest {
private ClassTest classTestObj;
#BeforeMethod
public void callClassConstructor() {
classTestObj = //call class constructor
}
#BeforeClass
public void setUpClass() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public boolean isValidTest() {
Boolean result = classTestObj.isValid();
Assert.assertEquals(result);
}
}
As I mentioned in the before comment, you can make use of MockedStatic to mock the static method - https://javadoc.io/static/org.mockito/mockito-core/4.4.0/org/mockito/Mockito.html#static_mocks
So your code will somewhat look like the below one if you are making use of Mockito instead of PowerMockito.
#RunWith(MockitoJUnitRunner.class)
public class ClassTest
{
#Mock
private Object mockAxis2ConfigurationContextFactoryObject;
#Test
public boolean isValidTest() {
try (MockedStatic<Axis2ConfigurationContextFactory> mockedStatic = mockStatic(Axis2ConfigurationContextFactory.class)) {
mockedStatic.when(()->Axis2ConfigurationContextFactory.getConfigurationContext()).thenReturn(mockAxis2ConfigurationContextFactoryObject);
Boolean result = classTestObj.isValid();
Assert.assertEquals(result);
}
}
This question already has answers here:
How to mock private method for testing using PowerMock?
(6 answers)
Closed 5 years ago.
I have a method which is private . Now, I do not want to call this private method while doing unit test on execute() method. I have tried with PowerMockito and all, but with all type of mockings it still enter into the private method.
Please suggest with workable testcase. Would appreciate the same.
#Component
public class Employee implements SuperClass {
#Autowired
private FileTraverse fileTraverse;
#Override
public void execute() throws Exception {
List<String> traverse = fileTraverse.getFiles();
Boolean t = isFileTraversed(traverse);
}
private Boolean isFileTraversed(List<String> param1) {
Boolean flag;
//do some DB operation and return flag;
}
}
#glytching is right. The best variant it's to extract method in a new service/component and create mock for one. In this case, your code is testable, you can re-use this component ...
BUT in case if you have only one use case for this method and you don't want to create a service/component just for one method, helper method, you can change the method visibility level from private to protected or package-default. In this case, you can override this method in subclass for testing and work with this sub-class. What you should do :
create a subclass for the class that you want to test and use the instance of this subclass instead of the target class.
--service that you have and need to test one
public class MainService {
#Autowired
private SecondService secondService;
public Object getResultFromMainService(){
return getResultFromMainServiceFromPrivate();
}
--here I changed 'private' into 'default-package'
Object getResultFromMainServiceFromPrivate(){
return secondService.getResult();
}
}
_
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = ServiceOverrideTestConfiguration.class)
public class MainServiceTest {
#Autowired
#Qualifier("subMainService") // or add #Primary and don't use Qualifier
private MainService service;
#Autowired
private SecondService secondService;
#Test
public void test(){
Object result = service.getResultFromMainService();
--here, method getResultFromMainService call inside the overrided
method that we can change
assertNotNull(result);
}
}
#ContextConfiguration
#Import(ApplicationConfigure.class)
class ServiceOverrideTestConfiguration {
#Bean("subMainService")
// or add #Primary and don't use Qualifier
MainService mainServiceSubBean(){
return new MainServiceUnderTest();
}
}
class MainServiceUnderTest extends MainService{
#Override
Object getResultFromMainServiceFromPrivate(){
return "SOME DEFAULT";
}
}
! Pls, consider this approach only as a workaround in rare cases when you need to mock/stub some method and you can't use PowerMock or any other libs. Better, try to do refactoring and bring testability in your code
Don't mock private methods.
See the suggestion below:
#Component
public class Employee implements SuperClass {
#Autowired
private FileTraverse fileTraverse;
#Override
public void execute() throws Exception {
List<String> traverse = fileTraverse.getFiles();
Boolean t = isFileTraversed(traverse);
}
private Boolean isFileTraversed(List<String> param1) {
Boolean flag;
//do some DB operation and return flag;
}
}
So inside isFileTraversed - you will have a DB operation. This operation will probably be executed through a DAO/Repository object.
So your code will probably look like:
#Component
public class Employee implements SuperClass {
#Autowired
private FileTraverse fileTraverse;
#Autowired
private DatabaseAccessDao dbAccess;
#Override
public void execute() throws Exception {
List<String> traverse = fileTraverse.getFiles();
Boolean t = isFileTraversed(traverse);
}
#Override
private Boolean isFileTraversed(List<String> param1) {
Boolean flag;
flag = dbAccess.checkFileTraversed(param1);
return flag;
}
}
What you need to do is to mock the public checkFileTraversed() method on the DatabaseAccessDao class.
1) Don't #Autowire on fields - prefer constructor injection.
2) Are you sure you want to return a Boolean? Is "null" allowed as a return value? If not - consider using the primitive boolean type;
Everybody else is right. You should try to avoid mocking private methods as much as you can. And if you really need to mock it, just drop the private to put it in default scope.
BUT
For the sake of completeness, you can indeed to it with PowerMock. Here is an example using PowerMock and EasyMock.
public class Employee {
public void execute() {
// If our mock is working, isFileTraversed will return false
assertThat(isFileTraversed(Collections.emptyList())).isFalse();
}
private Boolean isFileTraversed(List<String> param1) {
return true;
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(Employee.class)
public class EmployeeTest {
#Test
public void execute() throws Exception {
Employee employee = PowerMock.createPartialMockForAllMethodsExcept(Employee.class, "execute");
PowerMock.expectPrivate(employee, "isFileTraversed", Collections.emptyList()).andReturn(false);
PowerMock.replay(employee);
employee.execute();
PowerMock.verify(employee);
}
}
I have a class under test which contains a method which has an inner anonymous class. One of the methods in the anonymous class calls a method from the class under test, but Mockito doesn't seem to realize this.
public class ClassUnderTest {
Dependency dependency;
public ClassUnderTest(Dependency d) {
dependency = d;
}
public void method() {
dependency.returnsObservable().observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io()).subscribe(new Observer<SupportClass> {
/* Other methods omitted */
public void onComplete() {
outerMethod();
})
}
public void outerMethod() {
blah;
}
}
My test code:
public class TestClass {
ClassUnderTest underTest;
Dependency dependency;
#Before
public void setUp() throws Exception {
dependency = Mockito.mock(Dependency.class);
underTest = Mockito.spy(new ClassUnderTest(dependency));
}
#Test
public void method() throws
Mockito.when(dependency.returnObservable()).thenReturn(Observable.just(new SupportClass());
Mockito.doNothing().when(underTest).outerMethod();
underTest.method();
Mockito.verify(underTest).outerMethod();
}
}
For some reason that I can't seem to figure out, Mockito can't detect that outerMethod() is being called, even though I have manually verified by stepping through line by line in the debugger. I have also verified that the call to the dependency object returns the proper observable with the correct content, and the onComplete() and outerMethod() methods do get called. I'm just confused why Mockito doesn't detect it as such.
This is the error that it spits out:
Wanted but not invoked:
classUnderTest.outerMethod();
-> at (file and line number)
However, there was exactly 1 interaction with this mock:
classUnderTest.method();
-> at (file and line number)
Is there anything obvious I'm missing?
You're changing between schedulers so it can cause some issues when testing (your code may reach the verify method before the actual method is invoked
Check this article explaining how to test asynchronous code with RxJava and Mockito
TL;DR
Add a TestRule that set all schedulers to trampoline so it behaves synchronously:
public class TrampolineSchedulerRule implements TestRule {
#Override
public Statement apply(final Statement base, Description d) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
RxJavaPlugins.setIoSchedulerHandler(
scheduler -> Schedulers.trampoline());
RxJavaPlugins.setComputationSchedulerHandler(
scheduler -> Schedulers.trampoline());
RxJavaPlugins.setNewThreadSchedulerHandler(
scheduler -> Schedulers.trampoline());
RxAndroidPlugins.setInitMainThreadSchedulerHandler(
scheduler -> Schedulers.trampoline());
try {
base.evaluate();
} finally {
RxJavaPlugins.reset();
RxAndroidPlugins.reset();
}
}
};
}
}
I have an abstract method checkStatus() which has implementations in Checker.java class. But when I execute the Junit test case on abstract class method validate() that in-turn calls checkStatus(), fails due to missing spring dependency in Checker.java class.
Details provided below.
Abstract class:
public abstract class MyAbstractClass
{
protected abstract boolean checkStatus();
public boolean validate()
{
//Some code
return checkStatus();
}
}
Implementation class:
public class Checker extends MyAbstractClass
{
#Autowired
private StatusHelper helper;
public void setHelper(StatusHelper helper){
this.helper = helper;
}
#Override
public boolean checkStatus() throws Exception{
if(null == helper){
throw new Exception("Helper is null");
}
return helper.validateStatus();
}
}
JUnit test:
class AbstractClassTest
{
MyAbstractClass absClass = Mockito.mock(Checker.class, Mockito.CALLS_REAL_METHODS);
#Test
public void testStatusOfChecker()throws Exception {
boolean status = absClass.validate();
assertEquals(status, true);
}
}
I believe I can inject the helper object manually like the following
Checker check = mock(Checker.class);
StatusHelper helper = mock(StatusHelper.class);
check.setHelper(helper);
but the problem here is, I cannot inject directly to absClass object as the setHelper() is not inherited.
I can instead write test case directly to subclass, but I needed this way to test some other functionality in validate() method of abstract class.
Can someone help me how to set helper object to the sub class or is there different way to do it in Junit? Any help or links that contain relevant info is highly appreciable.
Thanks,
The only way to test an abstract class is by testing an implementation (which could be an anonymous class).
public class AbstractClassTest {
#Test
public void testStatusOfChecker() throws Exception {
MyAbstractClass object = new MyAbstractClass() {
protected boolean checkStatus() {
return true; //this is the place to provide the expected value
}
}
boolean status = absClass.validate();
assertEquals(status, true);
}
}
If you want to test the Checker implementation then you must not mock it.
public class CheckerTest {
#Test
public void test() {
StatusHelper helper = mock(StatusHelper.class);
Checker checker = new Checker();
checker.setHelper(helper);
when(helper.validate()).thenReturn(true);
boolean status = checker.validate();
assertEquals(status, true);
}
}
By the way I strongly recommend to use constructor injection (see Why field injection is evil). The test would then look like this
public class CheckerTest {
#Test
public void test() {
StatusHelper helper = mock(StatusHelper.class);
Checker checker = new Checker(helper);
when(helper.validate()).thenReturn(true);
boolean status = checker.validate();
assertEquals(status, true);
}
}
We have lots of selenium tests running through junit, and they all have a few steps which need to run before the actual tests. For this we have a parent TestCase class which has some #Before and #After methods in it.
Now, due to a new feature of our site I would like to parameterise part of this set up, I'd like to create a new annotation to put on some tests to indicate to the setup() method that the setup is slightly different, whilst allowing the others to use the default. So, is it possible to reflectively access the test method about to be run in an #Before method?
eg.
class SomeTest extends MyTestCase {
#Test
#Flavour(Red.class)
public void testRedFlavouredHomepage() {
testHomepage();
}
#Test
public void testBlueFlavouredHomepage() { // assuming Blue is my default flavour
testHomepage();
}
public void testHomepage() {
// test some stuff
}
}
You can do this using #Rule (with the later versions of JUnit >= 4.9). If you have a class which implements TestRule, specifically apply(), you can do extra things before your test gets run. The Description is passed to the apply method, which contains the annotations on your method:
Using #Deprecated as an example:
public class ExtraSetupTest {
#Rule
public TestRule moreSetup = new TestRule() {
public Statement apply(Statement base, Description description) {
return statement(base, description);
}
private Statement statement(final Statement base,
final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
if (description.getAnnotation(Deprecated.class) != null) {
System.out.println("more setup here");
}
base.evaluate();
}
};
}
};
#Test
public void noExtraSetup() {
System.out.println("noExtraSetup");
}
#Test
#Deprecated
public void withExtraSetup() {
System.out.println("withExtraSetup");
}
}
This produces as output:
noExtraSetup
more setup here
withExtraSetup
I'd rather suggest to use different test classes for those 2 methods.
class MyTestCase {
#Before
public void setUp() {
/* Default setup */
}
public void testHomepage() {
// test some stuff
}
}
class MyRedTestCase extends MyTestCase {
#Before
public void setUp() {
super.setUp();
/* Red setup */
}
}
And then you can put your tests into 2 different classes extending from MyTestCase and MyRedTestCase respectively.
class BlueTest extends MyTestCase {
#Test
public void testBlueFlavouredHomepage() { // assuming Blue is my default flavour
testHomepage();
}
}
class RedTest extends MyRedTestCase {
#Test
public void testRedFlavouredHomepage() {
testHomepage();
}
}
You can do it another way as well, without introducing new classes. Declare an absract (or concrete with the default value) method in your parent class.
class MyTestCase {
protected abstract Flour getFlour();
}
And your child class will look like this
class SomeTest extends MyTestCase {
private Flour flour;
#Test
public void testRedFlavouredHomepage() {
flour = Flour.RED;
testHomepage();
}
#Test
public void testBlueFlavouredHomepage() { // assuming Blue is my default flavour
flour = Flour.BLUE;
testHomepage();
}
public void testHomepage() {
// test some stuff
}
protected abstract Flour getFlour() {
return flour;
}
}
I'd say the 1st solution is "cleaner"; even though you have to create additional classes, you don't include logic of different types in one class (like in the anti-pattern God object).