0

If I use @Spy, it will help me to mock methods. but it doesn't work for private variable initialization

FieldSetter.setField(discoveryService, discoveryService.getClass().getDeclaredField("discoveryURL"), discoveryUrl);

If I remove @spy, FieldSetter works to initialize mock private variables. My code with @spy:

           @InjectMocks
/*line 5*/ @Spy
    private Class object;
     
    @Test
    void getFetchDiscoveryTest() throws IOException, NoSuchFieldException {

        String discoveryUrl = "https://ffc-onenote.officeapps.live.com/hosting/discovery";

/*line 15*/ FieldSetter.setField(object, object.getClass().getDeclaredField("discoveryURL"), discoveryUrl);
/*line 16*/ doThrow(IOException.class).when(object).getBytes(any());
/*line 17*/ when(object.getBytes(any())).thenThrow(new IOException("IO issue"));
        assertThrows(Exception.class, () -> object.getWopiDiscovery());

here if I putted line #5, then line #15 not works and line #16 working good. why If i have @spy, FieldSetter not works. how to make FieldSetter working for @spy as well ?

Prasanth Rajendran
  • 4,570
  • 2
  • 42
  • 59
Velmurugan A
  • 348
  • 3
  • 7
  • As far as I know, Mockito won't work with static methods / variables. ([see here for more info](https://stackoverflow.com/questions/4482315/why-doesnt-mockito-mock-static-methods)) You might have to use PowerMock on top. – maloomeister Jul 09 '20 at 05:34
  • What do you mean by "FieldSetter not works"? It throws exception? Do nothing? – talex Jul 09 '20 at 05:54
  • This is a demonstration that you need to modify your API. In particular, it seems you should be using _dependency injection_ and possibly passing in the URL as a constructor parameter. – chrylis -cautiouslyoptimistic- Jul 09 '20 at 06:06
  • regarding dependency injection: am getting private variable initialisation from property file. hence it should be initialised in test as well, since it already present in application.yml. FieldSetter not works means : that private variable value still not initialised , even though we are setting it via fieldsetter. but no error or exception. – Velmurugan A Jul 13 '20 at 07:37

2 Answers2

1

you can Inject values for private attributes of an instance using org.springframework.test.util.ReflectionTestUtils

@Service
public class SampleDiscoveryService{

    @Value("${props.discoveryUrl}")
   private String discoveryUrl;
}

Let's say above is service class, the value for discoveryUrl can be injected using


   @ExtendWith(MockitoExtension.class)
class SampleDiscoveryServiceTest {

    @InjectMocks
    private SampleDiscoveryService sampleDiscoveryService = null;

    @BeforeEach
    void setup() {
       ReflectionTestUtils.setField(sampleDiscoveryService, "discoveryUrl", "https://ffc-onenote.officeapps.live.com/hosting/discovery");
    }


Prasanth Rajendran
  • 4,570
  • 2
  • 42
  • 59
1

Do not use FieldSetter, use ReflectionTestUtils.setField() and it will be fine.

DAJ
  • 96
  • 2