Like unit test methods that interact with System (or Android) classes

How do you manage to write unit tests that interact with system classes, i.e. Android Framework classes?

Imagine you have these classes:

public class DeviceInfo {
    public final int screenWidth, screenHeight;
    public final String model;

    public DeviceInfo(int screenWidth, int screenHeight, String deviceModel) {
        this.screenWidth = screenWidth;
        this.screenHeight = screenHeight;
        this.model = deviceModel;
    }

}

public class DeviceInfoProvider {
    private final Context context;

    public DeviceInfoProvider(Context context) {
        this.context = context;
    }

    public DeviceInfo getScreenParams() {
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        windowManager.getDefaultDisplay().getMetrics(metrics);
        int screenWidth = metrics.widthPixels;
        int screenHeight = metrics.heightPixels;
        String model= Build.MODEL;
        DeviceInfo params = new DeviceInfo(screenWidth, screenHeight, model);
        return params;
    }
}

How can I write a test to check the correct behavior of a method DeviceInfoProvider.getScreenParams().

The following test passes, but it is very ugly and fragile:

@Test
public void testGetScreenParams() throws Exception {
    // Setup
    Context context = spy(RuntimeEnvironment.application);
    DeviceInfoProvider deviceInfoProvider = new DeviceInfoProvider(context);

    // Stub
    WindowManager mockWindowManager = mock(WindowManager.class);
    Display mockDisplay = mock(Display.class);
    when(context.getSystemService(Context.WINDOW_SERVICE)).thenReturn(mockWindowManager);
    when(mockWindowManager.getDefaultDisplay()).thenReturn(mockDisplay);
    doAnswer(new Answer() {
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            DisplayMetrics metrics = (DisplayMetrics) invocation.getArguments()[0];
            metrics.scaledDensity = 3.25f;
            metrics.widthPixels = 1081;
            metrics.heightPixels = 1921;
            return null;
        }
    }).when(mockDisplay).getMetrics(any(DisplayMetrics.class));

    // Run
    DeviceInfo deviceInfo = deviceInfoProvider.getScreenParams();

    // Verify
    assertThat(deviceInfo.screenWidth, equalTo(1081));
    assertThat(deviceInfo.screenHeight, equalTo(1921));
    assertThat(deviceInfo.model, equalTo(Build.MODEL));
}

How would you improve this?

Note. I am currently using Robolectric, Mockito and PowerMock.

+4
source share
1 answer

. , . , .

public interface DisplayProvider {
    public int widthPixels;
    public int heightPixels;
}

public interface BuildProvider {
    public string Model;
}

, , , ( ).

public class DeviceInfoProvider {
    private final DisplayProvider display;
    private final BuildProvider build;

    public DeviceInfoProvider(DisplayProvider display, BuildProvider build) {
        this.display = display;
        this.build = build;
    }

    public DeviceInfo getScreenParams() {
        int screenWidth = display.widthPixels;
        int screenHeight = display.heightPixels;
        String model = build.Model;
        DeviceInfo params = new DeviceInfo(screenWidth, screenHeight, model);
        return params;
    }
}

Unit test

@Test
public void testGetScreenParams() throws Exception {
    // Arrange
    DisplayProvider mockDisplay = mock(DisplayProvider.class);
    BuildProvider mockBuild = mock(BuildProvider.class);        
    DeviceInfoProvider deviceInfoProvider = new DeviceInfoProvider(mockDisplay, mockBuild);

    when(mockDisplay.widthPixels).thenReturn(1081);
    when(mockDisplay.heightPixels).thenReturn(1921);
    when(mockBuild.Model).thenReturn(Build.MODEL);

    // Act
    DeviceInfo deviceInfo = deviceInfoProvider.getScreenParams();

    // Assert
    assertThat(deviceInfo.screenWidth, equalTo(1081));
    assertThat(deviceInfo.screenHeight, equalTo(1921));
    assertThat(deviceInfo.model, equalTo(Build.MODEL));
}
+6

Source: https://habr.com/ru/post/1661877/


All Articles