0

I'm trying to mock an class that uses JAXRS and this class are a spring component.

@Component
public class PostmanClient {

  private WebTarget target;

  public PostmanClient() {
    Client client = ClientBuilder.newClient();
    target = client.target(...);
  }

  public String send(String xml) {
    Builder requestBuilder = target.request(MediaType.APPLICATION_XML_TYPE);
    Response response = requestBuilder.post(Entity.entity(xml, MediaType.APPLICATION_XML_TYPE));
    return response.readEntity(String.class);
  }
}

This is my test method:

@Test
public void processPendingRegistersWithAutomaticSyncJob() throws Exception {
  PostmanClient postmanClient = mock(PostmanClient.class);
  String response = "OK";
  whenNew(PostmanClient.class).withNoArguments().thenReturn(postmanClient);
  when(postmanClient.send("blablabla")).thenReturn(response);

  loadApplicationContext(); // applicationContext = new ClassPathXmlApplicationContext("/test-context.xml");
}

When i debug the postmanClient instance, its a instance created by Spring and not a mock. How can i avoid this behavior and get a mock instance ?

Sandro Simas
  • 1,268
  • 3
  • 21
  • 35
  • 3
    It's generally a bad idea to mix mocking into an integration test. Either don't load beans via Spring with `loadApplicationContext`, or use a different profile to load a manually stubbed PostmanClient for your tests. – Thorn G Jun 26 '14 at 21:14
  • Yes, but i don't want create a restful server to respond the postmanClient. The other way is to use a framework that mock restful services like restito or mock-server. – Sandro Simas Jun 27 '14 at 02:33
  • http://stackoverflow.com/questions/10906945/mockito-junit-and-spring/10924843#10924843 This question should give you some idea on how to do it. Though I am not recommend doing so, especially for unit testing – Adrian Shum Jun 27 '14 at 07:58

7 Answers7

0

If you are using PowerMock with Spring, you should consider following tips:
1. Use @RunWith(SpringJunit4Runner.class)
2. Use @ContextConfiguration("/test-context.xml") // load spring context before test
3. Use @PrepareForTest(....class) // to mock static method
4. Use PowerMockRule
5. The simplest way to mock a spring bean is to use springockito

Back To You Question:
If I don't understand you wrong, you have PostmanClient defined in spring context, which means, you only need use springockito to achieve your goal, just follow the tutorial on springockito page.

Jaiwo99
  • 9,687
  • 3
  • 36
  • 53
  • I don't want to use SpringJunit4Runner because i need to load datasets on database with DBUnit before spring context load. I try to use spring-test-dbunit but the framework listener always execute after spring context listener. Because of this i choose to load dataset and create the application context programmatically. Doing this way i need to create the mocks before all mentioned above. – Sandro Simas Jun 27 '14 at 02:31
  • @SandroSimas, you may use jUnit Spring Rule. Like in my example. https://github.com/thekingnothing/mockito-junit-spring-rules But I doubt that you need mock object in integration tests. – Artur Zagretdinov Mar 01 '16 at 09:37
0

You can use BDD framework Spock to write UT for your Spring Framework. With Spock Spring extension (Maven: groupId:org.spockframework, artifactId:spock-spring), you can load Spring context in your unit test.

@WebAppConfiguration
@ContextConfiguration(classes = Application.class)
class MyServiceSpec extends Specification {
    @Autowired
    UserRepository userRepository
}

If you have some beans you want to mock them instead of loading from Spring context, you can add following annotation on the bean you want to mock.

@ReplaceWithMock

This article has the detailed intro about how to write UT for your Spring app with Spock.

Yang Lifan
  • 445
  • 6
  • 15
0

Im not sure what is wrong with your implementation. Maybe PostmanClient should be an interface instead of class?

However I've implemented a similar unit test in my practice/test project. Maybe it will help:

https://github.com/oipat/poht/blob/683b401145d4a4c2bace49f356a5aa401fe81eb1/backend/src/test/java/org/tapiok/blogi/service/impl/PostServiceImplTest.java

user2170710
  • 140
  • 1
  • 1
  • 6
0

Register your mock with Spring-ReInject before the application context starts in your test's constructor. The original bean will be replaced with a mock, and the mock will be used by Spring everywhere, including injected fields. The original bean will be never created.

Sergey Grigoriev
  • 709
  • 7
  • 15
0

There is an option to fake Spring bean with just plain Spring features. You need to use @Primary, @Profile and @ActiveProfiles annotations for it.

I wrote a blog post on the topic.

luboskrnac
  • 23,973
  • 10
  • 81
  • 92
0

I've created the example to answer another question, but also cover your case. Simple replace MockitoJUnitRunner via SpringJUnit4ClassRunner.

In nutshell, I create Java Spring Configuration which includes only classes which should be tested/mocked and returns mocked object instead really object, and then give Spring does it work. Very simple and flexible solution.

It also works fine with MvcMock

Artur Zagretdinov
  • 2,034
  • 13
  • 22
0

As of Spring Boot 1.4.x you can use new annotation called @MockBean.

luboskrnac
  • 23,973
  • 10
  • 81
  • 92