2016-03-21 141 views
0

我注意到我的PHPUnit測試運行速度很慢,對於涉及GroupUsers的每個測試用例來說,差不多8秒左右。我開始調試,發現我的模擬靜態類仍在執行中,大部分時間消耗在監聽器中,這是在創建GroupUser時引發的事件。此事件從數據庫獲取用戶列表,然後使用我正在嘲笑的靜態類BrioMailer發送相應的電子郵件。嘲笑靜態方法嘲諷

我有一個靜態類,僅用於發送電子郵件。我有幾個方法可以改變模板和郵件選項,然後調用self::sendEmail實際發送郵件。

我正在使用Laravel 5,我不希望實際發送電子郵件,所以我已打開假裝模式。但是我注意到,即使在嘲笑類中調用的方法仍在執行時,我通過在郵件程序方法中輸入一些調試代碼並運行我的單元測試來驗證這一點。

我的測試案例

public function testNotificationSentToMemberWhenNewGroupMediaIsSaved() 
{ 
    $brioMailer = \Mockery::mock('alias:BrioMailer'); 

    $data = self::getRandomCommunityWithAssociatedData(); 

    $community = $data['community']; 
    $admin = $data['admins'][0]; 

    $firstUser = $data['users'][0]; 
    $firstUser->created_by = $admin->id; 
    $secondUser = $data['users'][1]; 
    $secondUser->created_by = $admin->id; 

    $notifications = $secondUser->notificationPreferences; 
    $notifications->{'new-media-member'} = 1; 
    $secondUser->notificationPreferences()->save($notifications); 

    $asset = factory(Asset\Video::class)->make(); 
    $asset->community()->associate($community); 
    $asset->user()->associate($admin); 
    $asset->save(); 

    $group = factory(Group::class)->make(); 
    $group->community()->associate($community); 
    $group->created_by = $admin->id; 
    $group->save(); 

    foreach([$firstUser, $secondUser, $admin] as $user) { 
     $groupUser = factory(GroupUser::class)->make(); 
     $groupUser->user_id = $user->id; 
     $groupUser->group_id = $group->id; 
     $groupUser->created_by = $admin->id; 
     $groupUser->save(); 
    } 

    $groupMedia = factory(GroupMedia::class)->make(); 
    $groupMedia->asset()->associate($asset); 
    $groupMedia->user()->associate($firstUser); 
    $groupMedia->group()->associate($group); 
    $groupMedia->published_date = date('Y-m-d H:i:s', strtotime('-1 day')); 

    $this->assertTrue($groupMedia->save()); 

    $brioMailer->shouldReceive('newMediaItemMember')->with($secondUser, $firstUser, $groupMedia); 
} 

我已驗證的問題是,事件監聽器正在高達每用戶8秒的「假裝」,以發送電子郵件。雖然我嘲笑對象,但它似乎仍然執行靜態方法。

我首先想到我需要將它添加到Laravel的IoC容器中,但是這只是一個自動加載的靜態類,它從應用程序的不同部分調用並且最初不存儲在IoC中。

有一點需要注意的是,朝測試用例底部的那一行似乎正常工作。如果我改變了shouldReceive() - > with()中參數的順序,那麼它開始拋出錯誤。

我只是不知所措,爲什麼靜態方法調用沒有擊中模擬對象,以及它是爲什麼它會試圖發送電子郵件。

任何協助或方向進一步閱讀將不勝感激。

+1

你不會喜歡它,但正確的解決方案是讓你的設計得到修復,不要從靜態調用發送電子郵件。注入一個適當的對象負責發送電子郵件到你需要的任何地方,並在你的測試中嘲笑它。注意:你的測試是完全不可讀的。考慮提取燈具創建(至少到一個方法,但閱讀測試數據建設者和母親對象)。 –

+0

是的,今天早上決定是否應該使用服務提供程序或事件與偵聽器發送郵件。尋找靜態類非常麻煩的測試。這也是使用Model Factories和Faker模擬測試數據,但我仍然需要設置關係進行測試。當然,我可以將這個提取到另一個方法,但是那個方法必須返回一個相關的對象數組,每個測試都是不同的。 –

回答