Featured image of post Dubbo在單元測試如何注入@DubboReference 避免Null Point Exception

Dubbo在單元測試如何注入@DubboReference 避免Null Point Exception

沉寂了一點,決定回歸TDD,但一開始就發現項目中的DubboReference無法被@Mock給替代,最後使用Reflection解決這個問題

前陣子工作實在是太忙了,寫了很多很爛的code出來,然後效能很差,依賴很多,分層也不夠清晰,讓我想到之前在御諾時就有實踐過的TDD,當時我說的一口好code,說TDD可以幫助架構、重構,有助於在爛code出現時提前嗅到它的味道,但從御諾離職後我就沒再寫過單元測試了,ㄏㄏ。

之前在接案公司時是說寫單元測試會不統一,有人有寫有人沒寫,不好跟客戶交代,換到現在尋頂時則是專案太大,開發進度太趕,我就有點懶得寫了,再加上一開始項目其實有很多Dependency不存在我們這邊,存在伺服器那,寫單元測試的意願就直線下降了

直到最近寫了一坨爛code被K得滿頭包,決定要來解決一下這個問題,但在剛開始時就遇到一個問題,項目的@Dubbo無法被SpringBoot的@Mock給mock掉

1
2
3
4
5
public class UserController {
@DubboReference
UserDubboService userDubboService;
  
}
1
2
3
4
5
6
7
8
@RunWith(MockitoJUnitRunner.class)
@Slf4j
public class UserControllerTest {
    @InjectMocks
    UserController userController;
    @Mock //這個會拋出null point exception
    UserDubboService userDubboService;
}

這問題在GitHub上也有人反映

spring-boot-test @MockBean 对 dubbo-reference 失效

後來試過很多方式,比如說把@Autowired加在UserDubboService上面,或是把DubboServiceInterface加上@Component註解都沒辦法完成,最後是使用了反射(Reflection)去反向注入這個Bean進去

Code如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
@RunWith(MockitoJUnitRunner.class)
@Slf4j
public class UserControllerTest {
    @InjectMocks
    UserController userController;
   	//@Mock 不用在透過Mockito去注入測試依賴
    UserDubboService userDubboService;

    @Before
    public void setUp() throws IllegalAccessException, NoSuchFieldException {
        userDubboService = Mockito.mock(UserDubboService.class);
        // 使用反射注入 glUserService
        Field field = userController.getClass().getDeclaredField("userDubboService");
        field.setAccessible(true);
        field.set(userController, userDubboService);
    }
}

就可以在呼叫userController時,去mock掉@DubboReference的bean了

Licensed under CC BY-NC-SA 4.0