Robię test jednostkowy, który wymaga niektórych obiektów, które wstrzyknięto wiosną, więc używam:

@RunWith(SpringRunner.class)
@Import({BConfig.class})
public class ATest {
    private A a;

    @Autowired
    private B b;

    @Before
    public void init() {
        a = new A(b);
    }
}

Jednak klasa BCONFIG ma pola autoryzowane C, którego potrzebuję w tym teście:

class BConfig {
    @Autowired
    C c;

    @Bean
    public getB() {
        return new B();
    }

    // other method code will use field c
}

Pole AutoWired C otrzyma dane z Redis w @Postconstruct, które nie istnieją w teście jednostkowym. Jeśli nie pominię, test jednostkowy zostanie zgłoszenie błędu z powodu danych Redisa nie istnieje.

Mam rozwiązanie do wykonywania C do 2 podklasowych CProdukcja i CUNITTEST z nich implementuje interfejs C, a następnie aktywny profil używany CUNITTEST w teście jednostki. Jest to jednak jakiś rodzaj inwazyjny, ponieważ jeśli nie wykonaj testu jednostki, interfejs C jest bezużyteczny.

Czy jest lepszy sposób, aby to zrobić?

0
jean 25 listopad 2019, 09:49

1 odpowiedź

Najlepsza odpowiedź

Rozważ użycie:

@RunWith(SpringRunner.class)
@ContextConfiguration({BConfig.class})
class ATest {

   @MockBean // will place a mock implementation of C to the context instead of real one that tries to connect with Redis.
   C c;

   ...
}

Zauważ, że będzie działać bezproblemowo, jeśli C jest interfejsem. W przeciwnym razie spróbuje stworzyć pełnomocnik przez dziedzictwo (coś, co rozciąga się z C), a jeśli C ma jakiś kod związany z Redisem w konstruktorze, może nadal próbować go nazywać.

Aktualizacja 1

Na podstawie komentarza OP, próbując wyjaśnić odpowiedź:

Po rozpoczęciu kontekstu aplikacji wiosennej w zasadzie rozwiązuje wszystkie fasole i wstrzykuje, co jest potrzebne.

Najpierw rozwiązuje definicje fasoli (metadane) - prawdziwą klasę, zakres itp., A następnie tworzy fasolę w kolejności, która pozwoli wtrysku. Na przykład klasa IT A ma pole klasy B (oba są fasolą), a następnie sprężyna musi utworzyć B najpierw B, a następnie utwórz A i wstrzyknij B w A.

Teraz @MockBean jest hakiem istotnym dla testów. Mówi kontekstowi Wiosennego zastosowania stosowanego w testowaniu, że zamiast regularnej definicji fasoli, że sprężyna jest w stanie przeanalizować z klas @Configuration lub znajdź komponent z tytułu @Component adnotacja umieszczona na nim, powinien użyć makiety - coś, co jest generowane w czasie wykonywania z ramami jak Mockito.

Ta makieta może później zostać wykorzystana do określenia oczekiwań (patrz Mockito Podstawowy samouczek, istnieje wiele osób w Internecie), ale co ważniejsze dla twojej sprawy, nie łączy się z Redisem, ponieważ ta próbna implementacja nie ma żadnych Redisu kod.

Aktualizacja 2

Konfiguracja powinna być przepisana w następujący sposób:

@Configuration
public class BConfig {

    @Bean
    public getB() {
        return new B();
    }
    @Bean
    public C c() {
       return new C();
    }


    // other method code will use field c:
    // if for example D uses C: then you can:

    @Bean
    public D d(C c) {
     return new D(c);
    } 
}
2
Mark Bramnik 25 listopad 2019, 10:39