2013-09-25 15 views
8

Mam do czynienia z problemami przedrzeźniającymi usługi wstrzyknięte w ramach innych usług w ramach struktury Spring. Tu jest mój kodu:Usługi symulacyjne w ramach innej usługi wiosennej z użyciem mockito

@Service("productService") 
public class ProductServiceImpl implements ProductService { 

    @Autowired 
    private ClientService clientService; 

    public void doSomething(Long clientId) { 
     Client client = clientService.getById(clientId); 
     // do something 
    } 
} 

Chcę mock ClientService wewnątrz mojego testu, więc próbowałem następujące:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:/spring-config.xml" }) 
public class ProductServiceTest { 

    @Autowired 
    private ProductService productService; 

    @Mock 
    private ClientService clientService; 

    @Test 
    public void testDoSomething() throws Exception { 
     when(clientService.getById(anyLong())) 
       .thenReturn(this.generateClient()); 

     /* when I call this method, I want the clientService 
     * inside productService to be the mock that one I mocked 
     * in this test, but instead, it is injecting the Spring 
     * proxy version of clientService, not my mock.. :(
     */ 
     productService.doSomething(new Long(1)); 
    } 

    @Before 
    public void beforeTests() throws Exception { 
     MockitoAnnotations.initMocks(this); 
    } 

    private Client generateClient() { 
     Client client = new Client(); 
     client.setName("Foo"); 
     return client; 
    } 
} 

clientService wewnątrz productService jest wersja Wiosna proxy, a nie makiety że chcieć. Czy można robić to, co chcę z Mockito?

Odpowiedz

0

Istnieje więcej sposobów, aby to osiągnąć, najbardziej prosty sposób to zrobić będzie don't use field injection, but setter injection co oznacza, trzeba mieć:

@Autowired 
public void setClientService(ClientService clientService){...} 

w swojej klasie usługi, a następnie można wstrzykiwać makiety do służby w Klasa testu:

@Before 
public void setUp() throws Exception { 
    productService.setClientService(mock); 
} 

important: Jeśli jest to tylko test jednostki, należy rozważyć nie używać SpringJUnit4ClassRunner.class, ale MockitoJunitRunner.class, tak, że można również użyć pola wstrzyknąć do swoich pól.

+1

Dzięki, próbowałem to rozwiązanie i działało w porządku, ale nie mogę zmienić wstrzyknięciem setter w tej usługi, więc moje rozwiązanie było usuń automatycznie zaznaczoną adnotację na moich testach i utwórz usługę ręcznie, jak na przykład: '@InjectMocks private ProductService productService = new ProductServiceImpl();' – br4zuca

+0

@ br4zuca możesz to zrobić za pomocą '@InjectMocks private ProductService productService', nie init to ręczne, niech makiety ito to zrób. – Jaiwo99

+1

Próbowałem zostawić init mockito 'productService' z' @ InjectMocks', ale nie zadziałało, ponieważ 'ProductService' to interfejs, który rzucił:' org.mockito.exceptions.base.MockitoException: typ 'ProductService' to interfejs ", więc nie był w stanie utworzyć instancji. – br4zuca

4

Trzeba opisywanie ProductService z @InjectMocks:

@Autowired 
@InjectMocks 
private ProductService productService; 

Ten wstrzyknie ClientService makiety do swojej ProductService.

+0

Dzięki Debojit, ale zdałem sobie sprawę, że nie ma sposobu, aby użyć zastrzyków wiosennych w połączeniu z pozorowanymi zastrzykami mockito ... więc moim rozwiązaniem było stworzenie ProductService przez ręce i wstrzyknięcie mocks '@ InjectMocks' tak jak powiedziałeś , ale nie używając '@ Autowired': ' @InjectMocks private ProductService productService = new ProductServiceImpl(); ' – br4zuca

+0

To dziwne. Używałem tych dwóch adnotacji razem. Przetestowałeś to. Czy istnieje wyjątek podczas korzystania z tych dwóch razem. –

+0

Tak, przetestowałem go bardzo często, nawet z '@ InjectMocks' na ProductService, w środku clientService było ładowane z proxy wiosny zamiast wyśmiewanego obiektu. Może wersja testowa, której używasz, różni się od używanej, moja wersja to 3.0.1.RELEASE, jaka jest twoja wersja? – br4zuca

0

Oprócz

@Autowired 
@InjectMocks 
private ProductService productService; 

Dodaj następującą metodę

@Before 
public void setup() { 
    MockitoAnnotations.initMocks(this); 
}