I want to test a MVP-Pattern. So i have a Presenter class, which shall invoke the View methods when certain buttons are clicked. Now I want to verify, that the Presenter really invokes the Method, so I wrote these tests:
Test Class:
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.runners.MockitoJUnitRunner;
import static org.mockito.Mockito.verify;
#RunWith(MockitoJUnitRunner.class)
public class MainPresenterTest {
#Mock
private MainContract.View view;
private MainPresenter presenter;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
presenter = new MainPresenter(view);
}
#Test
public void handleScanButtonClicked() {
presenter.handleScanButtonClicked();
verify(view).showScanScreen();
}
#Test
public void handleBackButtonClicked() {
presenter.handleBackButtonClicked();
verify(view).showMainScreen();
}
}
Presenter Class:
public class MainPresenter implements MainContract.Presenter {
private final MainContract.View view;
public MainPresenter(MainContract.View view) {
this.view = view;
}
#Override
public void handleScanButtonClicked() {
view.showScanScreen();
}
#Override
public void handleBackButtonClicked() {
view.showMainScreen();
}
}
MainContract Interface
public interface MainContract {
/** handles UI-interaction **/
interface Presenter {
void handleScanButtonClicked();
void handleBackButtonClicked();
}
/** handles showing/hiding UI-elements and screens **/
interface View {
void showScanScreen();
void showMainScreen();
void showWebViewScreen();
}
}
My Testing Dependencies in build.gradle:
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-all:1.10.19'
Test Error Message:
Wanted but not invoked:
view.showMainScreen();
-> at com.whatsthat.androidapp.MainPresenterTest.handleBackButtonClicked(MainPresenterTest.java:36)
Actually, there were zero interactions with this mock.
Wanted but not invoked:
view.showMainScreen();
-> at com.whatsthat.androidapp.MainPresenterTest.handleBackButtonClicked(MainPresenterTest.java:36)
Actually, there were zero interactions with this mock.
at com.whatsthat.androidapp.MainPresenterTest.handleBackButtonClicked(MainPresenterTest.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Wanted but not invoked:
view.showScanScreen();
-> at com.whatsthat.androidapp.MainPresenterTest.handleScanButtonClicked(MainPresenterTest.java:30)
Actually, there were zero interactions with this mock.
Wanted but not invoked:
view.showScanScreen();
-> at com.whatsthat.androidapp.MainPresenterTest.handleScanButtonClicked(MainPresenterTest.java:30)
Actually, there were zero interactions with this mock.
at com.whatsthat.androidapp.MainPresenterTest.handleScanButtonClicked(MainPresenterTest.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
Process finished with exit code -1
My Project Structure
When I now run the tests without an AVD running, they will fail. I want to run those tests on my local machine only, and there should be no interactions with Android specificly, right? But to let the tests pass, I need to start an AVD, and build + deploy the APK.
Why is this, and how can I run those kind of tests properly on my local machine?
Thanks in advance
You are not telling the framework what it should do when it encounters this line
view.showScanScreen()
and
view.showMainScreen()
do
doNothing().when(view).showScanScreen();
doNothing().when(view).showMainScreen();
You test methods will be like this
#Test
public void handleScanButtonClicked() {
doNothing().when(view).showScanScreen();
presenter.handleScanButtonClicked();
verify(view).showScanScreen();
}
#Test
public void handleBackButtonClicked() {
doNothing().when(view).showMainScreen();
presenter.handleBackButtonClicked();
verify(view).showMainScreen();
}
If you want to run your tests on your local machine's JVM, then you need to put them in test package, not in androidTest package. androidTest is used for instrumentation tests and will require Android framework to run.
Check out this post for their differences.
Related
I have Cucumber tests. The stack for framework is Cucumber 6 / Junit 4.13 / Spring 5.2 / Spring-boot-starter 2.3.
For running Cucumber tests in parallel I use #ScenarioScope annotation to make autowiring instances to be recycled between scenarios.
Tests launch fine when I use CucumberRunner. E.g.:
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {"pretty", "html:target/cucumber-reports.html"},
features = {"classpath:features"},
glue = {"<some_glue_class>"})
public class CucumberRunnerTest {
}
But when I try run some Junit tests (only, without Cucumber) I get an error.
E.g. Context:
#Configuration
#Import({BeanConfigClass.class})
public class DefaultContext {
// ...
}
Instance:
#ScenarioScope
#Component
public class Foo {
// ...
}
Test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = DefaultContext.class)
public class SomeTest {
#Autowired
private Foo foo;
#Test
public void fooTest(){
//some test
}
}
Error:
java.lang.IllegalStateException: No Scope registered for scope name 'cucumber-glue'
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:357)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:675)
at Foo$$EnhancerBySpringCGLIB$$1cf6c75d.replace(<generated>)
at test.SomeTest.fooTest(SomeTest.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Question:
I understand that I need to use a kind of CucumberRunner to make Spring understand cucumber-glue scope. But how to implement it?
I would have the ability to create specific bean, but the class CucumberScenarioScope is package-private in io.cucumber.spring. So it doesn't work:
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static io.cucumber.spring.CucumberTestContext.SCOPE_CUCUMBER_GLUE;
import static io.cucumber.spring.CucumberScenarioScope; //is not visible!
#Configuration
public class CustomScopeConfig {
#Bean
public BeanFactoryPostProcessor beanFactoryPostProcessor(){
return factory -> factory.registerScope(SCOPE_CUCUMBER_GLUE, new CucumberScenarioScope());
}
}
I'm writing a test that calls a method from another service:
// Setup mocks
private GoalService goalService;
private Principal principal;
private Goal goal;
private SecurityService securityService;
#Before
public void setup() {
goalService = new GoalService();
principal = mock(Principal.class);
goal = mock(Goal.class);
securityService = mock(SecurityService.class, Mockito.RETURNS_DEEP_STUBS);
}
#Test
public void testRequesterOwnsGoalIsTrue() {
doReturn(1).when(securityService).getUserIdByPrincipal(principal);
when(goal.getUsersUserId()).thenReturn(1);
boolean userOwnsGoal = goalService.requesterOwnsGoal(principal, goal);
assertEquals(true, userOwnsGoal);
}
During debug, when I call securityService.getUserIdByPrincipal(principal) I get a NPE. I am not sure why. Ideally, what I want is for the method call to return 1, I don't care about testing those function internal in this unit test.
Actual Code
Boolean requesterOwnsGoal(Principal principal, Goal goal) {
Optional<Goal> optionalGoal = Optional.ofNullable(goal);
if (optionalGoal.isPresent()) {
return secService.getUserIdByPrincipal(principal) == optionalGoal.get().getUsersUserId();
}
throw new StandardUserException("Requesting user does not have access to goal");
}
Stack:
java.lang.NullPointerException
at com.habicus.core.service.Goal.GoalService.requesterOwnsGoal(GoalService.java:170)
at com.habicus.core.service.Goal.GoalServiceTest.testRequesterOwnsGoalIsTrue(GoalServiceTest.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
It should be doReturn(1).when(securityService).getUserIdByPrincipal(any(principal)); to make it work.
Or
doReturn(1).when(securityService).getUserIdByPrincipal(any(Principal.class));
The code shown so far indicates that you are in fact creating a mock object. But you are not injecting that mock into your class under test!
Just creating mocks isn't sufficient. You have to ensure that they get used by the code you are testing!
Most likely that is your problem here, but as we still don't have a [mcve] we can't be sure.
I am trying to unit test the following method in Android:
#Override
public void onTryAgain() {
mView.showLoading();
mGetLoginSsoUseCase.execute(
getLoginSsoLink(),
new GetSsoLinkUseCase.Params(mUrl));
}
In which getLoginSsoLink() returns a callback object:
private ICallback<GetLoginSsoLinkResult> getLoginSsoLink() {
return new ICallback<GetLoginSsoLinkResult>() {
#Override
public void onResult(GetLoginSsoLinkResult result) {
// some code
}
#Override
public void onKoError(KOException exception) {
// some code
}
#Override
public void onConnectivityError(ConnectivityException exception) {
// some code
}
#Override
public void onGenericError(Exception exception) {
// some code
}
};
}
My unit test using Mockito is like that:
#Test
public void WhenCallOnTryAgain_ThenShowLoadingIsCalledInView(){
doNothing().when(mGetSsoLinkUseCase).execute(
FAKE_GET_LOGIN_SSO_LINK_RESULT_CALLBACK,
FAKE_GET_SSO_LINK_USE_CASE_PARAMS);
mPresenter.onTryAgain();
verify(mGetSsoLinkUseCase).execute(
FAKE_GET_LOGIN_SSO_LINK_RESULT_CALLBACK,
FAKE_GET_SSO_LINK_USE_CASE_PARAMS);
}
Where the fake vars are:
private static final ICallback<GetLoginSsoLinkResult> FAKE_GET_LOGIN_SSO_LINK_RESULT_CALLBACK =
new ICallback<GetLoginSsoLinkResult>() {
#Override
public void onResult(GetLoginSsoLinkResult result) {}
#Override
public void onKoError(KOException exception) {}
#Override
public void onConnectivityError(ConnectivityException exception) {}
#Override
public void onGenericError(Exception exception) {}
};
private static final GetSsoLinkUseCase.Params FAKE_GET_SSO_LINK_USE_CASE_PARAMS =
new GetSsoLinkUseCase.Params(FAKE_SSO_URL);
If I run the test, I get the following error:
Argument(s) are different! Wanted: mGetSsoLinkUseCase.execute(
com.xxx.xxxforstores.presenter.LoginSsoPresenterTest$1#8317c52,
com.xxx.xxxforstores.domain.usecase.GetSsoLinkUseCase$Params#68e965f5
);
-> at com.xxx.xxxforstores.presenter.LoginSsoPresenterTest.WhenCallOnTryAgain_ThenShowLoadingIsCalledInView(LoginSsoPresenterTest.java:111)
Actual invocation has different arguments: mGetSsoLinkUseCase.execute(
com.xxx.xxxforstores.mvp.presenter.LoginSsoPresenter$1#76f2bbc1,
com.xxx.xxxforstores.domain.usecase.GetSsoLinkUseCase$Params#6f27a732
);
-> at com.xxx.xxxforstores.mvp.presenter.LoginSsoPresenter.onTryAgain(LoginSsoPresenter.java:115)
Comparison Failure:
Argument(s) are different! Wanted: mGetSsoLinkUseCase.execute(
com.xxx.xzzforstores.presenter.LoginSsoPresenterTest$1#8317c52,
com.xxx.xxzforstores.domain.usecase.GetSsoLinkUseCase$Params#68e965f5
);
-> at com.xxx.xxxforstores.presenter.LoginSsoPresenterTest.WhenCallOnTryAgain_ThenShowLoadingIsCalledInView(LoginSsoPresenterTest.java:111)
Actual invocation has different arguments: mGetSsoLinkUseCase.execute(
com.xxx.xxxforstores.mvp.presenter.LoginSsoPresenter$1#76f2bbc1,
com.xxx.xxxforstores.domain.usecase.GetSsoLinkUseCase$Params#6f27a732
);
-> at com.xxx.xxxforstores.mvp.presenter.LoginSsoPresenter.onTryAgain(LoginSsoPresenter.java:115)
at
com.xxx.xxxforstores.presenter.LoginSsoPresenterTest.WhenCallOnTryAgain_ThenShowLoadingIsCalledInView(LoginSsoPresenterTest.java:111)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at
org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at
org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at
org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at
org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at
org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at
org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at
org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at
org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at
org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at
org.junit.runners.ParentRunner.run(ParentRunner.java:363) at
org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:78)
at
org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:84)
at
org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
at
org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:161)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at
com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at
com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at
com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at
com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)
I have a little experience in unit test so I figure that I am probably doing something wrong, what I have to change to test a method like that?
1) If mGetLoginSsoUseCase is a mock then you do not really need to set-up the .execute method with doNothing. Nothing will happen by default anyway
2) You cant really go for exact objects in the verify as one of the params is simply created on the fly: new GetSsoLinkUseCase.Params(mUrl). I would go for any(class) checks which should be enough in your case:
verify(mGetSsoLinkUseCase).execute(
Mockito.any(ICallback.class),
Mockito.any(GetSsoLinkUseCase.Params.class));
Can someone explain me why my JUnit test fail:
notNullMethodTest() uses #NotNull --> success
nonnullMethodTest() uses #Nonnull --> fail
Unexpected exception, expected<java.lang.NullPointerException> but
was<java.lang.IllegalArgumentException>
package com;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.validation.constraints.NotNull;
import org.junit.Test;
public class AnnotationTest {
private void nonnullMethod(#Nonnull String arg) {
Objects.requireNonNull(arg);
}
#Test(expected = NullPointerException.class)
public void nonnullMethodTest() {
nonnullMethod(null);
}
private void notNullMethod(#NotNull String arg) {
Objects.requireNonNull(arg);
}
#Test(expected = NullPointerException.class)
public void notNullMethodTest() {
notNullMethod(null);
}
}
Here the StackTrace:
java.lang.Exception: Unexpected exception, expected<java.lang.NullPointerException> but was<java.lang.IllegalArgumentException>
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.IllegalArgumentException: Argument for #Nonnull parameter 'arg' of com/AnnotationTest.nonnullMethod must not be null
at com.AnnotationTest.$$$reportNull$$$0(AnnotationTest.java)
at com.AnnotationTest.nonnullMethod(AnnotationTest.java)
at com.AnnotationTest.nonnullMethodTest(AnnotationTest.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:19)
... 19 more
Thanks
IntelliJ has recently started generating this assertion code by default. If you don't want this behavior, you can deactivate it in the compiler settings:
The configuration behind the "configure annotations" button allows you to specify which annotations should be taken into account. This is why it behaves differently when you switch annotations.
I have the below test class, which has been stripped to the bare minimum needed to reproduce the issue:
#RunWith(Parameterized.class)
#ContextConfiguration(locations = { "classpath:restful-service-test-context.xml" })
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class ResftulServiceTest {
#Autowired
#Qualifier("failedAspectTestMessage")
private String failedAspectTestMessage;
#Autowired
private ProviderService ProviderService;
private String methodName;
private Set valuesToReturnByMock;
private TestContextManager testContextManager;
public ResftulServiceTest(String methodName, String[] valuesToReturnByMockArray) {
this.methodName = methodName;
this.valuesToReturnByMock = new HashSet<>(Arrays.asList(valuesToReturnByMockArray));
}
#Parameterized.Parameters
public static Collection values() {
return Arrays.asList(new Object[][] { { "getCountries", new String[] { "GB", "US" } }, });
}
#Before
public void setUpSpringContext() throws Exception {
testContextManager = new TestContextManager(getClass());
testContextManager.prepareTestInstance(this);
}
#Test
public void testGetValues_Fail_MyException() throws Exception {
Method methodInProviderService = ProviderService.class.getDeclaredMethod(methodName);
Mockito.when(methodInProviderService.invoke(ProviderService))
.thenThrow(new MyException(failedAspectTestMessage, StatusCodeType.ERROR));
}
#Test
public void testGetValues_Fail_Exception() throws Exception {
Method methodInProviderService = ProviderService.class.getDeclaredMethod(methodName);
Mockito.when(methodInProviderService.invoke(ProviderService))
.thenThrow(new AspectException(failedAspectTestMessage));
}
}
If I run each of the tests separately, they work fine. However, if I run all of them, testGetValues_Fail_Exception fails on the Mockito line with error:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com<obfuscated>.ResftulServiceTest.testGetValues_Fail_Exception(ResftulServiceTest.java:111)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: com.<obfuscated>.MyException: FAILED_ASPECT_TEST_MESSAGE
... 40 more
If I replace the .thenThrow in testGetValues_Fail_MyException with .thenReturn, it all works fine, so at some point the isolation is being broken. How can I fix this problem?
Try using Mockito.reset() passing your mock. Usually this is done to prevent interaction between test. It resets the previously configured behavior of the mock. However, in your case I cannot give more details as you are using an unusual combination of Parameterized with Spring context and DirtiesContext.