網頁

2020/8/22

Java test mock random 考題

最近面試的問題,主要是測試對單元測試中mock的概念及依賴注入替換物件的概念。

題目如下,請問如何測試addTenWithRandom()中忽略隨機值的結果?

package com.abc.demo;

import java.util.Random;

public class DemoService {

    public int addTenWithRandom(int i) {
        return i + 10 + new Random().nextInt();
    }

}

這方法測試的困難在於new Random().nextInt()的值是不固定的,所以測試此方法就必須忽略其產生的隨機值,那該如何修改使其變得可測呢?

可設計一個介面RandomInterface並提供產生隨機數的方法nextInt()

RandomInterface

package com.abc.demo;

public interface RandomInterface {

    int nextInt();

}

設計一個類別RealRandom實作RandomInterfacenew Random().nextInt()進行包裝。

RealRandom

package com.abc.demo;

import java.util.Random;

public class RealRandom implements RandomInterface {
    @Override
    public int nextInt() {
        return new Random().nextInt();
    }
}

設計一個mock類別MockRandom實作RandomInterface,在此即可決定nextInt()回傳的random值。

MockRandom

package com.abc.demo;

public class MockRandom implements RandomInterface {
    @Override
    public int nextInt() {
        return 0;
    }
}

原程式中不要直接使用Random.nextInt()取得隨機值,改為使用成員RandomInterfacenextInt()來取得。RandomInterface的實例在建構DemoService時傳入,此即為依賴注入

DemoService

package com.abc.demo;

public class DemoService {

    private RandomInterface random;

    public DemoService(RandomInterface random) {
        this.random = random;
    }

    public int addTenWithRandom(int i) {
        return i + 10 + random.nextInt();
    }

}

在測試程式DemoServiceTests中可替換DemoService的成員RandomInterfaceMockRandom來測試。

DemoServiceTests

package com.abc.demo;

public class DemoServiceTests {

    public static void main(String[] args) {
        new DemoServiceTests().testAddTenWithRandomIgnoreRandomValue();
    }

    public void testAddTenWithRandomIgnoreRandomValue() {
        DemoService demoService = new DemoService(new MockRandom());
        assert demoService.addTenWithRandom(10) == 20;
    }

}

沒有留言:

張貼留言