NPE when calling MockitoAnnotations.initMocks() in AndroidTestCase - java

Trying to use mockito in my AndroidTestCase. I added the dependencies to the build.gradle:
final DEXMAKER_VERSION = '1.2'
dependencies {
// ...
androidTestCompile "com.google.dexmaker:dexmaker:${DEXMAKER_VERSION}"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:${DEXMAKER_VERSION}"
androidTestCompile 'org.mockito:mockito-core:1.10.19'
}
The TestCase with the mockito initialization:
public class UsersListPresenterTest extends AndroidTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
public void testInitialize() throws Exception {
}
}
But as soon as I add any attribute to the class, even before adding any annotation the test start to crash:
public class UsersListPresenterTest extends AndroidTestCase {
String mockString;
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
public void testInitialize() throws Exception {
}
}
With the following stacktrace
java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.Class java.lang.Object.getClass()' on a null object reference
at com.google.dexmaker.mockito.DexmakerMockMaker.getInvocationHandlerAdapter(DexmakerMockMaker.java:80)
at com.google.dexmaker.mockito.DexmakerMockMaker.getHandler(DexmakerMockMaker.java:75)
at org.mockito.internal.util.MockUtil.isMockitoMock(MockUtil.java:74)
at org.mockito.internal.util.MockUtil.isMock(MockUtil.java:66)
at org.mockito.internal.configuration.injection.scanner.MockScanner.isMockOrSpy(MockScanner.java:86)
at org.mockito.internal.configuration.injection.scanner.MockScanner.preparedMock(MockScanner.java:72)
at org.mockito.internal.configuration.injection.scanner.MockScanner.scan(MockScanner.java:61)
at org.mockito.internal.configuration.injection.scanner.MockScanner.addPreparedMocks(MockScanner.java:47)
at org.mockito.internal.configuration.InjectingAnnotationEngine.injectMocks(InjectingAnnotationEngine.java:96)
at org.mockito.internal.configuration.InjectingAnnotationEngine.processInjectMocks(InjectingAnnotationEngine.java:62)
at org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:56)
at org.mockito.MockitoAnnotations.initMocks(MockitoAnnotations.java:108)
at com.myproject.presentation.UsersListPresenterTest.setUp(UsersListPresenterTest.java:28)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1853)
What am I doing wrong?

You could try to replace
MockitoAnnotations.initMocks(this);
with this
System.setProperty("dexmaker.dexcache", getContext().getCacheDir().getPath());
It works for me. See ref here

Its a bug in dexmaker for which I have submitted a fix:
https://github.com/crittercism/dexmaker/pull/24

For me the solution was to use the Method Mockito.mock() for each Mocking Object instead of using MockitoAnnotations.initMocks(this);
So for example:
public class HomePresenterTest {
private Repository repository;
private HomePresenter presenter;
#Before
public void before() {
repository = mock(Respository.class);
presenter = new HomePresenter(repository);
}
//Your tests
}

I've created an issue there https://github.com/mockito/mockito/issues/392
Original answer with hotfix there https://stackoverflow.com/a/36642606/1224247

Related

Mocking a static method using powermockito

I am testing some legacy code and would like to mock any calls to a static logger method: LoggerFact.getLogger(Class class, String MethodName), here is what I tried:
#RunWith(PowerMockRunner.class)
#PrepareForTest({LoggerFact.class, MyClass.class, Logger.class})
public class MyClassTest
{
#Before
public void prepare() throws Exception
{
Logger mockedLogger = Mockito.mock(Logger.class);
PowerMockito.mockStatic(LoggerFact.class);
PowerMockito.when(LoggerFact.getLogger(MyClass.class, "test"))
.thenReturn(mockedLogger);
}
//My tests
}
The class that I am testing:
public class MyClass
{
public String methodToBeTested()
{
Logger logger = LoggerFact.getLogger(this.getClass(), "test");
logger.info("This is a test");
//some logic
return "SUCCESS";
}
}
But I am recieving this error when I do this from the prepare when():
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
Did I miss something? I checked a lot of older posts about this issue, but nothing worked for me.
Working example here. Tested with JDK 8 and JDK 11.
The following works for me. (I have found that the order of initialization can be crucial):
#RunWith(PowerMockRunner.class)
#PrepareForTest(LoggerFact.class)
public class MyClassTestCase {
private MyClass myClass = null;
#Before
public void setUp() {
PowerMockito.mockStatic(LoggerFact.class);
}
#Test
public void testMethodToBeTested() {
Logger mockLogger = Mockito.mock(Logger.class);
PowerMockito.when(LoggerFact.getLogger(eq(MyClass.class),eq("test"))).thenReturn(mockLogger);
myClass = new MyClass();
// test
myClass.methodToBeTested();
verify(mockLogger, times(1)).info(eq("This is a test"));
}
}
As requested, from build.gradle in the example link above, here are the versions of libraries:
dependencies {
testImplementation 'junit:junit:4.13.1'
testImplementation 'org.mockito:mockito-core:3.6.0'
testImplementation 'org.powermock:powermock-api-mockito2:2.0.7'
testImplementation 'org.powermock:powermock-module-junit4:2.0.7'
}

Mockito SpyBean throws an UnfinishedStubbingException

I'm trying to partially mock a service using Mockito's Spy, overriding a method to make it return consistent data for testing, but said spy throws an UnfinishedStubbingException for no apparent reason.
This is my test class:
#SpringBootTest
#RunWith(SpringRunner.class)
public class ApplicationIT {
private CompletableFuture<JobList> jobList;
#SpyBean
private Service serviceSpy;
#Before
public void setUp() {
initMocks(this);
jobList = new CompletableFuture<>();
jobList.complete(jobList.newBuilder()
.addAllJobs(jobTestData.getTestJob().getJobs()).build());
Mockito.doReturn(jobList).when(serviceSpy).fetchJob();
Mockito.doNothing().when(serviceSpy).reportSuccess(Mockito.any());
}
#Test
public void fetchJobCallTest() {
Mockito.verify(serviceSpy, timeout(60000).atLeastOnce()).fetchJob();
}
#Test
public void reportSuccessCallTest() {
Mockito.verify(serviceSpy, timeout(60000).atLeastOnce()).reportSuccess(Mockito.any());
}
}
Both tests fail with a org.mockito.exceptions.misusing.UnfinishedStubbingException pointing to Mockito.doReturn(jobList).when(serviceSpy).fetchJob(); at Mockito.doNothing().when(serviceSpy).reportSuccess(Mockito.any());
UnfinishedStubbingException means you are not mocking properly
this is not the right way of mocking a method... Mockito.doReturn(jobList).when(serviceSpy).fetchJob();
You can try below...
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();

Mock ReactiveSecurityContextHolder

how can I mock ReactiveSecurityContextHolder in the tests so it will be possible to get into the lambda flatmap
ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.flatMap(authentication -> {})
To mock Authentication held in the ReactiveSecurityContextHolder you need to use TestSecurityContextHolder and ReactorContextTestExecutionListener:
#RunWith(MockitoJUnitRunner.class)
public class ReactiveSecurityContextHolderTests {
#Mock
private Authentication authentication;
private TestExecutionListener reactorContextTestExecutionListener =
new ReactorContextTestExecutionListener();
#Before
public void setUp() throws Exception {
when(authentication.getPrincipal()).thenReturn("token");
TestSecurityContextHolder.setAuthentication(authentication);
reactorContextTestExecutionListener.beforeTestMethod(null);
}
#After
public void tearDown() throws Exception {
reactorContextTestExecutionListener.afterTestMethod(null);
}
//...tests...
}
Alternatively, you can use SpringRunner with #TestExecutionListeners annotation instead of MockitoJUnitRunner:
#RunWith(SpringRunner.class)
#TestExecutionListeners(ReactorContextTestExecutionListener.class)
public class ReactiveSecurityContextHolderTests {
private static Authentication authentication;
#BeforeClass
public static void setUp() throws Exception {
authentication = mock(Authentication.class);
when(authentication.getPrincipal()).thenReturn("token");
TestSecurityContextHolder.setAuthentication(authentication);
}
//...tests...
}
Find more information in the https://docs.spring.io/spring-security/site/docs/current/reference/html/test.html
You just need to add #WithMockUser("customUserName") on test.

Mockito.when().thenReturn() doesn't work or returns null

During the test there is a NullPointerException thrown. I tried to debug it and the only thing I worked out was that eventOptional is always null. Just as if Mockito.when().thenReturn() didn't work. Can anybody help? Here's my code for a tested service and for the test itself:
#Service
public class EventService {
#Autowired
public EventService(EventRepository eventRepository) {
this.eventRepository = eventRepository;
}
//...
public void updateEvent(EventDTO eventDTO) {
Optional<Event> eventOptional = eventRepository.findOneById(eventDTO.getId());
eventOptional.orElseThrow(() -> new BadRequestException(EVENT_NOT_FOUND));
//...
}
}
And the test class:
#RunWith(MockitoJUnitRunner.class)
public class EventServiceTest {
#Mock
private EventRepository eventRepository;
#InjectMocks
private EventService eventService;
private Event sampleEventFromDb;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
#Test
public void shouldUpdateEventTestAndWithProperTime() throws Exception {
EventDTO eventDTOMock = Mockito.mock(EventDTO.class);
sampleEventFromDb = Event.builder()
.name("name")
.startDateTime(LocalDateTime.now())
.placeName("place")
.description("description")
.publicEvent(true)
.owner(new User())
.build();
Mockito.when(eventRepository.findOneById(anyString())).thenReturn(Optional.of(sampleEventFromDb));
Mockito.when(eventDTOMock.getId()).thenReturn("1");
eventService.updateEvent(eventDTOMock); //NullPointerException
//...
}
}
I got this same error, after trying a lot of things I fixed it by replacing the anyString() method with any()
Try this:
Mockito.when(eventRepository.findOneById(any())).thenReturn(Optional.of(sampleEventFromDb));
Looks like the problem is that initMock is called twice: once by the runner and once by the setUp method. Running the test with the regular runner or removing the initMocks call from the setUp method fixes this problem.
Change anyList(), anyMap()..... to any(). After long debugging it is worked finally.

Dropwizard Integrated Testing with TestResource

Does anyone knows how to add a test Resource (i.e. one that is only for testing purposes and not added in run() method of the app)?
Here is an example:
public class MyTest {
#ClassRule
public static final DropwizardAppRule<TestConfiguration> RULE =
new DropwizardAppRule<TestConfiguration>(MyApp.class, "my-app-config.yaml");
#BeforeClass
public static void setUpBeforeClass() throws Exception
{
MyTest.RULE.getEnvironment().jersey().register(new JustForTestingResource());
}
#Test
public final void testTestResource()
{
Client client = new Client();
ClientResponse response = client.resource(
String.format("http://localhost:%d/rest/v1/test", RULE.getLocalPort()))
.get(ClientResponse.class);
assertThat(response.getStatus(), is(200));
}
}
and
public class JustForTestingRessource {
#GET
#Path("test")
#Produces(MediaType.APPLICATION_JSON)
public Response getInTestResource()
{
return Response.status(Status.OK).type(MediaType.TEXT_PLAIN).entity("get #Path(\"test\") is ok").build();
}
}
My problem is that the added resource is not added and I get resource not found 404 error response. It seems that I am registering the new resource after resource publishing and there is no refresh inside Dropwizard after start.
I dont want to extend my Application class and I dont want to insert test code into my real application code. Does anyone knows how to register the test resource without registering it in run() method of the Application?
This works, but a new class is needed:
public class TestService extends MyService{
#Override
public void run(
TestConfigurationconfiguration,
Environment environment) throws ClassNotFoundException
{
environment.jersey().register(new JustForTestingRessource());
super.run(configuration,environment);
}
}
Call in JUnit as already known:
#ClassRule
public static DropwizardAppRule<TestConfiguration> RULE =
new DropwizardAppRule<TestConfiguration>(TestService.class, "my-app-config.yaml");
Edit: Removing previous answer because it didn't solve your problem the way you wanted to do it.
I dug into the environment startup code and realized the reason why registering a controller didn't make it available is because jetty had already been started. If you stop jetty, register your controller and start jetty back up again, your resource will be available and you can use it in your test.
#BeforeClass
public static void setUpBeforeClass() throws Exception
{
MyTest.RULE.environment.applicationContext.stop()
MyTest.RULE.environment.jersey().register(new JustForTestingResource())
MyTest.RULE.environment.applicationContext.start()
}
You can test the Resource itself in a Jersey Container without starting a full dw-instance.
Check the "Testing Resources" section.
import static org.fest.assertions.api.Assertions.assertThat;
import static org.mockito.Mockito.*;
public class PersonResourceTest {
private static final PeopleStore dao = mock(PeopleStore.class);
#ClassRule
public static final ResourceTestRule resources = ResourceTestRule.builder()
.addResource(new PersonResource(dao))
.build();
private final Person person = new Person("blah", "blah#example.com");
#Before
public void setup() {
when(dao.fetchPerson(eq("blah"))).thenReturn(person);
// we have to reset the mock after each test because of the
// #ClassRule, or use a #Rule as mentioned below.
reset(dao);
}
#Test
public void testGetPerson() {
assertThat(resources.client().resource("/person/blah").get(Person.class))
.isEqualTo(person);
verify(dao).fetchPerson("blah");
}
}
I had the similar issue with the #ClassRule, maybe it can help to somebody..
In my test (Groovy) the invocation of RULE.getApplication() or getEnvironment() from #BeforeClass method returned null:
def setupSpec() {
RULE.application.run()
}
shown
java.lang.NullPointerException: Cannot invoke method run() on null object
I.e. RULE.testSupport had both null application and environment.
I found out that the call to
RULE.testSupport.before()
just before run() solves the error:
def setupSpec() {
RULE.testSupport.before()
RULE.application.run()
}
And then #AfterClass method:
def cleanupSpec() {
RULE.testSupport.after()
}
Or just use #Rule instead of #ClassRule and call
def setup() {
RULE.application.run()
}
inside of #Before method instead of #BeforeClass.
Though It seems strange, maybe there is some other better solution exists..
public class TestMain extends Main{
public static void main(String ... args) throws Exception {
new TestMain().run(args);
}
#Override
public void initialize(Bootstrap<AppConfiguration> bootstrap) {
super.initialize(bootstrap);
bootstrap.addBundle(
new MigrationsBundle<AppConfiguration>() {
#Override
public DataSourceFactory getDataSourceFactory(
AppConfiguration configuration) {
return configuration.getDataSourceFactory();
}
});
}
}

Categories