I have the following class to test.
public class ClassToTest {
private View view;
public ClassToTest(View view) {
this.view = view;
}
public void init() {
view.add(new ParamClass.OnSomething() {
#Override
public void onSomethingElse() {
view.doSomeWork();
}
});
}
}
Where view is
public class View {
public void add(OnSomething onSomething) {
}
public void doSomeWork() {
}
}
I have mocked view object, but no clue how to test the logic marked "Some logic here to test"
ParamClass is final.
public final class ParamClass {
public interface onSomething {
public void onSomethingElse();
}
}
Without making change to source, is there a way to unit test this using Mockito / Powermockito?
I'm trying to verify the invocation of doSomeWork()
#RunWith(PowerMockRunner.class)
#PrepareForTest({ ClassToTest.class })
public class TestClass {
#Mock View view;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
ClassToTest classToTest = new ClassToTest(view);
PowerMockito.doCallRealMethod().when(view).add(Mockito.any(ParamClass.OnSomething.class));
PowerMockito.whenNew(ParamClass.OnSomething.class)
.withAnyArguments()
.thenReturn(new ParamClass.OnSomething() {
#Override
public void onSomethingElse() {
view.doSomeWork();
}
});
classToTest.init();
Mockito.verify(view, Mockito.times(1)).doSomeWork();
}
}
Its throwing exception
java.lang.ArrayIndexOutOfBoundsException: 0
at org.powermock.api.mockito.internal.expectation.DefaultConstructorExpectationSetup.withAnyArguments(DefaultConstructorExpectationSetup.java:66)
at com.linkedin.android.lite.animations.TestClass.test(TestClass.java:29)
I figured out how to do it. Updating the answer.
public class TestClass {
#Mock View view;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void test() throws Exception {
ClassToTest classToTest = new ClassToTest(view);
classToTest.init();
ArgumentCaptor<ParamClass.OnSomething> captor =
ArgumentCaptor.forClass(ParamClass.OnSomething.class);
verify(view).add(captor.capture());
ParamClass.OnSomething onSomething = captor.getValue();
onSomething.onSomethingElse();
Mockito.verify(view, Mockito.times(1)).doSomeWork();
}
}
Well what are you exactly trying to test? If there is code inside onSomethingElse that calls other objects/methods then you can simply mock all those other calls and then use Mockito.verify(mockObjectHere).methodCalled() on those methods that were called, if you just want to implement testing for behaviour.
Related
Here is my test class.
#ExtendWith(MockitoExtension.class)
class DishServiceTest {
static MockedStatic<DaoFactory> daoFactoryDummy;
static MockedStatic<FileUtil> fileUtilDummy;
#Mock
DaoFactory daoFactory;
#Mock
DishDao dishDao;
#Spy
DishService dishService;
#BeforeAll
static void setUp() {
fileUtilDummy = Mockito.mockStatic(FileUtil.class);
daoFactoryDummy = Mockito.mockStatic(DaoFactory.class);
}
#AfterAll
static void close() {
daoFactoryDummy.close();
fileUtilDummy.close();
}
#Test
void deleteWithImage_id0_success() {
daoFactoryDummy.when(ServiceManager::getInstance).thenReturn(daoFactory);
when(daoFactory.createDishDao()).thenReturn(dishDao);
long id = 2;
String deleteDir = "/dish-image/2";
dishService.deleteWithImage(id, deleteDir);
verify(dishDao, times(1)).delete(id);
fileUtilDummy.verify(() -> FileUtil.deleteDishFolder(deleteDir));
}
#Test
void update_idSet_success() {
daoFactoryDummy.when(ServiceManager::getInstance).thenReturn(daoFactory);
when(daoFactory.createDishDao()).thenReturn(dishDao);
Dish dish = new Dish(2, "testName",
"testDescription", Category.DRINKS, BigDecimal.TEN, "/image21");
dishService.saveOrUpdate(dish);
verify(dishDao, times(1)).update(dish);
verify(dishDao, times(1)).close();
}
}
I mock static methods like this because DishService class gets dao object from DaoFactory.
Here is an example of DishService method
public class DishService {
public void saveOrUpdate(Dish newDish) {
try (DishDao dishDao = DaoFactory.getInstance().createDishDao()) {
long newDishId = newDish.getId();
if (newDishId == 0) {
dishDao.save(newDish);
} else {
dishDao.update(newDish);
}
}
}
}
And of DaoFactory
public class JDBCDaoFactory extends DaoFactory {
DBManager dbManager = DBManager.getInstance();
UserDaoMapper userDaoMapper = new UserDaoMapper();
DishDaoMapper dishDaoMapper = new DishDaoMapper();
OrderDaoMapper orderDaoMapper = new OrderDaoMapper();
OrderItemDaoMapper orderItemDaoMapper = new OrderItemDaoMapper();
#Override
public UserDao createUserDao() {
return new JDBCUserDao(dbManager.getConnection(),
userDaoMapper);
}
#Override
public DishDao createDishDao() {
return new JDBCDishDao(dbManager.getConnection(), dishDaoMapper);
}
#Override
public OrderDao createOrderDao() {
return new JDBCOrderDao(dbManager.getConnection(), orderDaoMapper,
orderItemDaoMapper);
}
}
And here is the exception I have
org.mockito.exceptions.misusing.MissingMethodInvocationException:
Also, this error might show up because:
you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified. Mocking methods
declared on non-public parent classes is not supported.
inside when() you don't call method on mock but on some other object. at
service.DishServiceTest.update_idSet_success(DishServiceTest.java:61)
Here is the line 61
The strangest thing here is that tests pass when I run them seperately, but if i press run all tests in class I get the exception above.
I want to create a test for presenter class using mockito tried few ways but getting error mention below. I am following these links here and here and my presenter class
public class SignInPresenterImpl extends BasePresenterImpl implements SignInPresenter {
private SignInView mSignInView;
private SignInInteractor mSignInInteractor;
/**
* Constructor
*
* #param signInView the associated SignIn view
*/
public SignInPresenterImpl(#NonNull final SignInView signInView) {
mSignInView = signInView;
mSignInInteractor = new SignInInteractorImpl();
}
#Override
public void onSignInClicked(final String email, final String password) {
// checking for validation
if (!ValidationUtil.checkEmail(email)) {
mSignInView.showErrorMessage(R.string.error_invalid_email);
return;
}
if (!ValidationUtil.checkPassword(password)) {
mSignInView.showErrorMessage(R.string.error_invalid_password);
return;
}
mSignInView.showLoading();
mSignInInteractor.login(email, password, new BaseInteractor.ApiListener() {
#Override
public void onSuccess(final CommonResponse commonResponse) {
//todo handle success
}
#Override
public void onFailure(final ApiError apiError, final Throwable throwable) {
if (isViewAttached()) {
mSignInView.hideLoading();
if (apiError != null) {
mSignInView.showErrorMessage(apiError.getMessage());
} else {
// resolve error through throwable
mSignInView.showErrorMessage(parseThrowableMessage(throwable));
}
}
}
});
}
}
and my presenter test class is
public class SignInPresenterImplTest {
#Mock
BaseInteractor.ApiListener listener;
#Mock
private SignInView mSignInView;
#Mock
private SignInInteractor mSignInInteractor;
private SignInPresenter signInPresenter;
#Before
public void setUp() throws Exception {
// Mockito has a very convenient way to inject mocks by using the #Mock annotation. To
// inject the mocks in the test the initMocks method needs to be called.
MockitoAnnotations.initMocks(this);
//Get a refrence to the class test.
signInPresenter = new SignInPresenterImpl(mSignInView);
}
#Test
public void signInAndShowProgress() {
signInPresenter.onSignInClicked("", "");
mSignInView.showErrorMessage("");
verify(mSignInView).showLoading("Loading");
}
}
mSignInView shows below error
Wanted but not invoked: mSignInView.showLoading("Loading");
Please suggest me how to implement test cases in a correct way what I am doing wrong in it.
Thanks in advance
In your method under test, the showLoading method is invoked with no attributes.. i think you should expect that and possibly verify that no error message has been shown:
#Test
public void signInAndShowProgress() {
signInPresenter.onSignInClicked("", "");
verify(mSignInView, times(0)).showErrorMessage(Mockito.any(String.class));
verify(mSignInView).showLoading();
}
I want to test that fan.setState method is called or not
class OffState implements State {
#Override
public void changeState(Fan fan) {
fan.setState(new OnState());
}
}
Like this:
#RunWith(MockitoJUnitRunner.class)
public class OffStateTest {
#Mock
private Fan fan;
#Test
public void testChangeState() {
//Arrange
OffState offState = new OffState();
//Act
offState.changeState(fan);
//Assert
Mockito.verify(fan).setState(Mockito.any(OnState.class));
}
}
I am trying to write a test for GWTP presenter, but for some reason mockito when() will not trigger. I stubbed method to return a mock, but it returns null, because as I said method when() is not working (or so I assume). Any ideas?
My unit test:
#RunWith(JukitoRunner.class)
public class PresenterATest {
#Inject
PresenterA presenterA;
PresenterA presenterASpy;
#Mock
ColumnProperties columnProperties;
#Before
public void setUp() throws ActionException {
MockitoAnnotations.initMocks(this);
presenterASpy = spy(presenterA);
}
#Test
public void presenterTest() {
setUpColumnPropertiesMock();
when(presenterASpy.getSelectedColumn()).thenReturn(columnProperties);
// adjust colors intervals with slider
presenterA.saveColumnIntervals(Arrays.asList(45.55, 59.9, 70.05, 100.15),
Arrays.asList("#e9a8ff", "#d3ffa6", "#ffffa6", "#a8d4ff", "#ffbca6"));
}
private void setUpColumnPropertiesMock() {
when(columnProperties.getName()).thenReturn("col1");
}
}
Presenter:
public class PresenterA {
#Inject
Settings settings;
public ColumnProperties getSelectedColumn() {
return settings.getSelectedColumn();
}
public void saveColumnIntervals(List<Double> intervals, List<String> colors) {
ColumnProperties columnProperties = getSelectedColumn();
columnProperties.setIntervalList(intervals); //Nullpointer here, because getSelectedColumn() returns null
columnProperties.setColorList(colors);
}
}
I have a test with 15-20 different test cases, I want to run the same test with twice with two different parameters which are supposed to be passed to the test's BeforeClass method, for instance:
public class TestOne {
private static ClassToTest classToTest;
#BeforeClass
public static void setUp() throws Exception {
classToTest = new ClassToTest("Argument1", "Argument2");
}
#Test
public void testOne() {
........roughly 15 - 20 tests here
}
public class TestTwo {
private static ClassToTest classToTest;
#BeforeClass
public static void setUp() throws Exception {
classToTest = new ClassToTest("Argument3", "Argument4");
}
#Test
public void testOne() {
........roughly 15 - 20 tests here, same as in TestOne
}
As you can see the only difference between these two tests is in the setup method, which passes different values to the constructor of the ClassToTest. I don't want to replicate the test methods in both classes, but would prefer either inheritance or some other intelligent way to achieve this in one class.
This seems like a perfect use case for JUnit4's #Parameters; see https://blogs.oracle.com/jacobc/entry/parameterized_unit_tests_with_junit or http://www.mkyong.com/unittest/junit-4-tutorial-6-parameterized-test/ . That said, you'll have to move the initialization from the setUp method to a constructor for the test class.
For what it's worth, here is how you would do it with TestNG:
public class TestFactory {
#Factory
public Object[] createTests() {
return new Object[] {
new ClassToTest("arg1", "arg2"),
new ClassToTest("arg3", "arg4")
};
}
}
public class ClassToTest {
public ClassToTest(String arg1, String arg2) {
this.arg1 = arg1;
this.arg2 = arg2;
}
#Test
public void testOne() {
// use arg1 and arg2
}
}
Thanks all for your quick replies. This is how I did it finally
public abstract class Base {
final HeavyObject heavy;
protected Base(HeavyObject heavy) {
this.param = param;
}
#Test
public void test() {
param.doSomething();
}
#Test
.............More tests here
}
public class FirstTest extends Base{
private static HeavyObject param;
#BeforeClass
public static void init() {
param = new HeavyObject("arg1", "arg2");
}
public FirstTest() {
super(param);
}
}
public class SecondTest extends Base{
private static HeavyObject param;
#BeforeClass
public static void init() {
param = new HeavyObject("arg3", "arg4");
}
public FirstTest() {
super(param);
}
}
Base is an abstract class which has all the tests and FirstTest and SecondTest create their own objects with different parameters and pass it to the abstract class to use it.
As per the documentation (http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html):
A subclass does not inherit the private members of its parent class.
However, if the superclass has public or protected methods for
accessing its private fields, these can also be used by the subclass.
How about this:
public class TestOne {
private static ClassToTest classToTest1, classToTest2;
#BeforeClass
public static void setUp() throws Exception {
classToTest1 = new ClassToTest("Argument1", "Argument2");
classToTest2 = new ClassToTest("Argument3", "Argument4");
}
#Test
public void testOne() {
testOneImpl(classToTest1);
testOneImpl(classToTest2);
}
public void testOneImpl(ClassToTest classToTest) {
// exact samew as whatever your current testOne() test method is
}
....
}
EDIT:
Or to keep method count down:
public class TestOne {
private static List<ClassToTest> classesToTest;
#BeforeClass
public static void setUp() throws Exception {
classesToTest = new ArrayList<>;
classesToTest.add( new ClassToTest("Argument1", "Argument2"));
classesToTest.add( new ClassToTest("Argument3", "Argument4"));
}
#Test
public void testOne() {
for (ClassToTest classToTest: classesToTest) {
... same test content as before
}
}