Unit-Tests and UI (static methods)

I don’t have a real question at all but as I converted our project from alpha to Beta(5 at the moment) I wanted to port our JUnit-Tests too. By doing this I ran over the problem that your UI.getCurrent now is a static method. As we try to inject nearly everything with CDI this is a real problem because popular mocking frameworks like Mockito can’t (and should not) mock static methods. In this state it is not very easy to test a method where UI is called because when I try to it calls the real static UI and recognizes that there isn’t a UI instance running and returns a NPE.
The only way out that I can see is to
manually build a stub object for UI and use this at testing
build an interface that calls the UI for me and returns it and never use UI directly from my code but only this interface but it is not very convenient.

What I usually do is just call UI.setCurrent(mock) before i run my tests… crude, but it works :slight_smile:

And the mock is a self written class that implements UI or do you use powermock to do this?

It depends on what I’m testing: if I’m testing a View, it’s usually a Mockito.mock(UI.class).


Ahh OK, but that won’t work anymore when you use a UI.getCurrent().removeAllComponents for example because removeAllComponents uses internally getContent which is a static method and therefore cannot be mocked with Mockito. As long as powermock is not an option for us we have to work around here with a gateway class that delivers us the UI Object.

edit: forget about that. it should work even with removeAllComponents but anyway I don’t think its a really good idea to begin integrating static methods in the framework itself becaus it causes serious hassle for testability.

The getCurrent() methods returning threadlocals are mostly available for convenience. The framework should not use them internally, and it should always be possible to get the “current” object in a non-static fashion. If there are any situations where it is not feasible, please report them to us.

Hey guys, what about this?

PowerMockito.mockStatic(UI.class); Mockito.when(UI.getCurrent()).thenReturn(Mockito.mock(UI.class)); That’s how I am doing right now, and it works on my UT.
It is a basic combination of PowerMock + Mockito. Good enough.

Cheers,
Pedro

Also, complementing, if you do it this way, you also have to include the following before the class body:

@RunWith(PowerMockRunner.class) @PrepareForTest({UI.class, Navigator.class, WhateverVaadinAPI.class}) public class TestClass { ... } Using this approach, we can even simulate a servlet context, a vaadin request, the UI instantiation, navigator retrieval through the UI current instance … everything you want. Hope you have success on it. :slight_smile:

Regards,
Pedro

HI Team,

i have below method and i am following the same way using poermockito but i am unable to simulate UI object and always getting Null

the below is the method i would like to write JUNIT

[color=#008000]
@Override
public void errorManagementViewSeeDetailsButtonClicked(Object source) {
boolean selectedRow = errorManagementTable.setSelectedRows();
if (selectedRow) {
ErrorTransactionType errorTransactionType = errorManagementTable.getSelectedError();
getUI().getNavigator().navigateTo(
UnbalanceErrorView.NAME + “/” + errorTransactionType.getCdSalesMarket() + “/” + errorTransactionType.getDaTrans() + “/”
+ errorTransactionType.getIdCustomer() + “/” + errorTransactionType.getDaOrder() + “/”
+ errorTransactionType.getIdOrder());
} else {
Notification.show(“Select at least one row to see details”, Notification.Type.WARNING_MESSAGE);
}
}

and so far i can simulate errorManagementTable by using EasyMock usage.

here is the code which i am using .
[/color]

[color=#FFA500]
@RunWith(PowerMockRunner.class)
@PrepareForTest({UI.class,Navigator.class})
public class ErrorManagementViewTest {

@InjectMocks
private ErrorManagementMainTable errorManagementTable;

@Mock
private ErrorManagementViewSeeDetailsButton seeDetails;

@Mock
private LogoutButton logout;

@Mock
private Button navigateToTransactionTypeManagementView;

@Mock
Notification notification;



private ErrorManagementView errorManagementView = new ErrorManagementView();

@Before
public void setUp() {
    
    /*ui = EasyMock.createMock(UI.class);
    errorManagementView.setUi(ui);*/
    
    errorManagementTable = EasyMock.createMock(ErrorManagementMainTable.class);
    errorManagementView.setErrorManagementTable(errorManagementTable);
    
    PowerMockito.mockStatic(Navigator.class);

}

@Test
public void testErrorManagementView() {

    // Arrange
    ErrorTransactionType errorTransactionType = new ErrorTransactionType();
    errorTransactionType.setCdSalesMarket("DE");
    errorTransactionType.setCdTransCat(1);
    errorTransactionType.setDaOrder(new Date());
    errorTransactionType.setErrorCorrected("Y");
    errorTransactionType.setErrorTypeDesc("TEST");
    errorTransactionType.setIdCustomer(11);
    errorTransactionType.setIdOrder("111");
    errorTransactionType.setTransactionCategoryDesc("TEST");

    PowerMockito.mockStatic(Navigator.class);
     MainUI mockManagerUI = mock(MainUI.class);
     UI.setCurrent(mockManagerUI);
    
    
    EasyMock.expect(errorManagementTable.setSelectedRows()).andReturn(true);
    EasyMock.expect(errorManagementTable.getSelectedError()).andReturn(errorTransactionType);
    EasyMock.replay(errorManagementTable);


    errorManagementView.errorManagementViewSeeDetailsButtonClicked(Object.class);

}

[/color]

[color=#008000]
}

any help please ???
[/color]

any suggestions??

Late answer is late. I think Johannes Dahlströms answer still is great. Refactor your code into not using statics anymore.

So in your example you should write following to have perfect mockable code

new Notification("Select at least one row to see details", Notification.Type.WARNING_MESSAGE)
  .show(getUi().getPage());