2015-09-18 3 views
-1

Для одного из моих вариантов использования, я должен издеваться над автозависимой зависимостью только в одном тестовом примере, в то время как я хочу, чтобы другие тесты использовали исходный.Mockito with Spring

public class A { 

    @Autowired 
    private B b; 
} 

Class TestA { 

    @Autowired 
    private A a; 

    void test1() { 
    //using B without mock. 
    } 

    void test2() { 
    // mock B b in A here 
    } 
} 

Я хочу высмеять переменную частного класса 'b' здесь, в некоторых конкретных тестах. Я знаю, если мне нужно издеваться над B в целом классе, я могу использовать @Mock, @InjectMocks и MockitoAnnotations.initMocks(), но это будет издеваться над «b» для других тестовых случаев, где я хочу оригинальное поведение.

+2

У вас может быть два класса испытаний, один с макетами и другой без макета. –

+0

@SubirKumarSao - Как правило, мы придерживаемся привычки хранить тестовые файлы с суффиксом * Test.java. Сохранение 2-х разных файлов сделает его путаным для других людей. – Amit

ответ

0

Вы можете просто создать макет объекта и временно назначить его переменной b. Что-то вроде

public void test1() { 
    //normal test 
} 

в то время как в другом:

public void test2() { 
    try { 
     B autowiredObject = b; //saving the original reference 
     b = mock(B.class); 
     when(b.someGetFunction()).thenReturn("it is mocked"); 
     //rest of your test 
    } finally { 
     b = autowiredObject; 
    } 
} 

Пожалуйста, обратите внимание на пункт finally. Он должен гарантировать, что состояние класса (автономная зависимость) будет восстановлено во время теста. Это очень важная практика, иначе неудача в вашем тесте может теоретически повлиять на ваши другие тесты в том же классе, чего вы всегда должны избегать.

+0

Как это должно работать, учитывая, что экземпляр B в объекте класса A не является тем же самым, что мы насмехались здесь в наших тестах? Мы не ввели насмешливое B в объект a класса A, правильно? – Amit

+0

«Мы не вводили насмешливый B ...?» - * Да, вы это сделали. * Здесь: "b = mock (B.class);" –

0

Как правило, вы не используете Spring для модульного тестирования, но полагаетесь на насмешливые зависимости и вводите их вручную в тестовый объект. Простой метод испытания поэтому может выглядеть следующим образом:

@Test 
public void testSomethingWithA() throws Exception { 
    // Arrange 
    A sut = new A(); 
    B mockedB = mock(B.class); 

    // inject B into A 
    Whitebox.setInternalState(sut, "b", mockedB); 

    // Act 
    Object retVal = sut.doSomething(); 

    // Assert 
    assertThat(retVal, is(equalTo(someExpectedValue))); 
} 

Если вы хотите, чтобы ввести реальный объект в вместо издевались объект (по какой-либо причине) просто переключитесь mockedB в Whitebox.setInternalState(...) с реальным объектом.

+0

Я использовал Deencapsulation.setField от JMockit, он не работал, дайте мне проверить, работает ли Whitebox.setInternalState. – Amit