我試圖寫在春天啓動的服務的簡單的單元測試。單元在春季啓動測試與模擬一個接口實現
該服務調用在其上返回用戶的一個實例的存儲庫的方法。 我試圖嘲笑知識庫,因爲我只想測試服務。
所以,庫代碼:
public interface UserRepository extends MongoRepository<User, String> {
User findByEmail(String email);
}
服務接口:
public interface UserService {
@Async
CompletableFuture<User> findByEmail(String email) throws InterruptedException;
}
服務實現:
@Service
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
// dependency injection
// don't need Autowire here
// https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-spring-beans-and-dependency-injection.html
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Async
public CompletableFuture<User> findByEmail(String email) throws InterruptedException {
User user = userRepository.findByEmail(email);
return CompletableFuture.completedFuture(user);
}
}
單元測試:
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
@InjectMocks
UserService userService;
@Mock
UserRepository mockUserRepository;
@Before
public void setUp() {
MockitoAnnotations.initMock(this);
}
@Test
public void mustReturnUser() throws InterruptedException {
String emailTest = "[email protected]";
User fakeUser = new User();
fakeUser.setEmail(emailTest);
when(mockUserRepository.findByEmail(emailTest)).thenReturn(fakeUser);
User user = userService.findByEmail(emailTest).join();
assertThat(user).isEqualTo(fakeUser);
verify(mockUserRepository).findByEmail(emailTest);
}
}
當我運行這個測試,我得到了一個MockitoException
:
org.mockito.exceptions.base.MockitoException:
Cannot instantiate @InjectMocks field named 'userService'.
...
Caused by: org.mockito.exceptions.base.MockitoException: the type 'UserService' is an interface.
除了使用界面,我試圖用真正的實現;改變測試這樣的:現在
@InjectMocks
UserServiceImpl userService;
,測試通過成功,但不會出現是正確的(至少對我來說)。 我喜歡測試春天開機使用(假設在我的系統的新版本,我實現了一個新的UserServicePostgreSQLImpl - 現在,我使用的MongoDB)的UserService。 (編輯:看到問題底部編輯)
我改變了單元測試如下:
@Autowired
@InjectMocks
UserService userService;
,但現在我得到了一個測試失敗:
Expected :[email protected]
Actual :null
出於某種原因,當我使用@Autowired
時,UserRepository
模擬不起作用。 如果我改變emailTest
在我的數據庫使用真實的電子郵件, 測試通過。 當我使用@Autowired
, 時,測試使用的是實際的UserRepository
而不是UserRepository
的Mock
版本。
任何幫助?
編輯:查看@msfoster和@dunni的答案,並思考得更好,我相信正確的方法是測試每個實現(在我的示例中,使用UserServiceImpl userService
)。
你不是測試實際的實現,是你在說什麼? 整個重點是測試你的接口的實現。 – msfoster
這正是我所說的!我可以測試真正的實現,如果在測試中我使用'UserServiceImpl userService',但是如果我創建另一個userService實現,我將需要編寫一個新的單元測試(好吧,這也是正確的),但我喜歡僅測試Spring正在使用的實現 –
請問您爲什麼要這麼做?似乎測試的目的不是測試服務,而是您的應用程序的一個方面。 – msfoster