Hot questions for Using Mockito in jakarta ee

Hot questions for Using Mockito in jakarta ee

Question:

I know that every method that doesn't do anything shouldn't be tested (or not even exist). The thing is, that my method does something normally, but for the test-scenario I have to mock that thing that it does. But I would still like to assert the parameters that it would send to the external thing.

Sounds more complicated than it is - Check my snippet for better understanding:

class A {
    @Inject
    private Mailer mailer; // Custom mailer class

    public void doSomething() {
        Date date = new Date(); // dynamic parameter I do not care about in the test
        String parameter = "test"; // The parameter I want to test later

        mailer.sendMail(parameter, date);
    }
}

class ATest {
    @Mock
    @Produces
    private Mailer mailer;

    @Inject
    private A classToTest;

    @Test
    public void testDoSomething() throws Exception {

        classToTest.doSomething();

        assertThat(??).isEqualTo("test"); //How can I get the value of parameter?
    }
}

As you can see I need to mock my emailer, so that I dont send a email everytime a test runs.

It would make no sense to promote parameter to a global variable.

Is there any way to test the value of parameter without changing the code of A? And if not what would be the best solution without messing up my class just for testing?


Answer:

You need to use Mockito.verify:

verify(mailer, times(1)).sendMail("test");

Verify checks what happened with your mocks: how many times a method was called, and what arguments were given to that method.


Update: If you want to exclude certain parameters, you can use org.mockito.Matchers.any - easier to have it as a static import. (NB: if you do ignore some parameters, then the ones you want to INCLUDE now have to be wrapped in org.mockito.Matchers.eq).

verify(mailer, times(1)).sendMail(eq("test"), any(Date.class));

Question:

Iam using mockito to perform testing and iam very much new to it. Iam getting a null pointer exception in the Mockito method and in the Onmessage method for the use of a object/variable declared. The code snippet is as below.

Class A.java

        Class A{

        @Inject
        CheckConnection connection;

        public void onMessage(Message m)
        {
            if(connection.IsInternetavailable==true) //Null pointer is occuring here
            {
               //Do something with Message 
            } 
            else
            {
              //Do something with Message 
            }
         }
       }

Class Atest.java-Mockito Class

        Class ATest
        {

         @InjectMocks
         A resource;

         @Mock
            CheckConnection connection;

         @Test
            public void shouldProcessMessage() throws JMSException {
                // Arrange
                final String Type = "MessageType";
                final String Body = "MessageBody"

                final ActiveMQTextMessage message = new ActiveMQTextMessage();
                message.setStringProperty("messageType", Type);
                message.setText(Body);

                // Act
                this.resource.onMessage(message);  //This method fails i.e. it gives null pointer exception
            }
        }

Answer:

First: the annotation is InjectMocks not InjectMock s is missing

Second: You need to initialize the mocks with this call MockitoAnnotations.initMocks(this); which should be in your set up method or first call in your test method.

Question:

Currently I'm trying to work with Mockito combined with rest. I'm not sure how to test my edit method in rest with Mockito and rest. The last block of code contains the part I can't figure out atm. I haven't worked with Mockito before so all tips are welcome.

This is the functionality i want to test:

@POST
@Path("edit/{id}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public Profile editProfile(Profile profile, @PathParam("id") Long id){
    Profile updatedProfile = profileService.getProfile(id);
    updatedProfile.setBiography(profile.getBiography());
    updatedProfile.setLocation(profile.getLocation());
    updatedProfile.setWebsite(profile.getWebsite());
    updatedProfile.setAvatar(profile.getAvatar());
    updatedProfile.setImage(profile.getImage());
    updatedProfile.setUpdated_at(new Date());
    return updatedProfile;
}

Setting up my TestClass here

Client client;
WebTarget root;
static final String PATH = "/MyApp/api/profile/";
static final String BASEURL = "http://localhost:8080" + PATH;
List<Profile> profileList = new ArrayList<Profile>();
Profile profile;

@Mock
ProfileDao profileDao;

@InjectMocks
private ProfileService profileService;

@Before
public void setUp() {
    this.client = ClientBuilder.newClient();
    this.root = this.client.target(BASEURL);
    profile = new Profile(1L,"biography", "location" ,"website","../avatar.jpg","../image.jpg" );
    for(int i = 0; i < 10; i++){
        profileList.add(profile);
    }
}

The Test function to edit an test: /profile/edit/1 - /profile/edit/{id}

// This part doesn't work. I'm not sure how to handle this part with mockito and rest

@Test
public void editProfileTest() { 
    String mediaType = MediaType.APPLICATION_JSON;        
    when(profileDao.find(1L)).thenReturn(new Profile(1L,"biography", "location" ,"website", "../avatar.jpg","../image.jpg"));
    final Entity<Profile> entity = Entity.entity(profileService.getProfile(1L), mediaType);

    Profile profileResult = this.root.path("edit/1").request().post(entity, Profile.class);
    assertThat(profileResult, is(profile)); // this doesn't match
}

Answer:

At first I wasn't really sure how to make the test valid but with the following piece of code I solved my problem.

Adjusted my Rest / Mockito test a little bit:

@Test
public void editProfileTest() { 
    String mediaType = MediaType.APPLICATION_JSON;        
    when(profileDao.find(2L)).thenReturn(profileList.get(0));
    final Entity<Profile> entity = Entity.entity(profileService.getProfile(2L), mediaType);
    Profile profileResult = this.root.path("edit/2").request().post(entity, Profile.class);
    assertThat(profileResult.getId(), is(profileService.getProfile(2L).getId()));
    assertThat(profileResult.getUser_id(), is(profileService.getProfile(2L).getUser_id()));
    assertThat(profileResult.getAvatar(), is(profileService.getProfile(2L).getAvatar()));
    assertThat(profileResult.getBiography(), is(profileService.getProfile(2L).getBiography()));
    assertThat(profileResult.getLocation(), is(profileService.getProfile(2L).getLocation()));
    assertThat(profileResult.getWebsite(), is(profileService.getProfile(2L).getWebsite()));
    assertThat(profileResult.getImage(), is(profileService.getProfile(2L).getImage()));
}

This is testing the method on /MyApp/profile/edit/{id} only. If you have examples for an integration test or references feel free to post about it. As I'm trying to learn some more about testing in general.