简体   繁体   English

如何模拟春豆?

[英]How to mock a spring bean?

I'm trying to mock an class that uses JAXRS and this class are a spring component. 我正在尝试模拟一个使用JAXRS的类,并且该类是spring组件。

@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. 当我调试postmanClient实例时,它是Spring创建的一个实例,而不是模拟对象。 How can i avoid this behavior and get a mock instance ? 我如何避免这种行为并获得模拟实例?

If you are using PowerMock with Spring, you should consider following tips: 如果将PowerMock与Spring一起使用,则应考虑以下提示:
1. Use @RunWith(SpringJunit4Runner.class) 1.使用@RunWith(SpringJunit4Runner.class)
2. Use @ContextConfiguration("/test-context.xml") // load spring context before test 2.使用@ContextConfiguration(“ / test-context.xml”)//在测试之前加载spring上下文
3. Use @PrepareForTest(....class) // to mock static method 3.使用@PrepareForTest(.... class)//模拟静态方法
4. Use PowerMockRule 4.使用PowerMockRule
5. The simplest way to mock a spring bean is to use springockito 5.模拟弹簧豆的最简单方法是使用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. 如果我不理解您的意思,您在spring上下文中定义了PostmanClient ,这意味着您只需要使用springockito来实现您的目标,只需按照springockito页面上的教程进行操作即可。

You can use BDD framework Spock to write UT for your Spring Framework. 您可以使用BDD框架Spock为您的Spring框架编写UT。 With Spock Spring extension (Maven: groupId:org.spockframework, artifactId:spock-spring), you can load Spring context in your unit test. 使用Spock Spring扩展(Maven:groupId:org.spockframework,artifactId:spock-spring),您可以在单元测试中加载Spring上下文。

@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. 如果您有一些想要模拟它们而不是从Spring上下文加载的bean,可以在想要模拟的bean上添加以下注释。

@ReplaceWithMock

This article has the detailed intro about how to write UT for your Spring app with Spock. 本文详细介绍了如何使用Spock为您的Spring应用程序编写UT。

Im not sure what is wrong with your implementation. 我不确定您的实现有什么问题。 Maybe PostmanClient should be an interface instead of class? 也许PostmanClient应该是接口而不是类?

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 https://github.com/oipat/poht/blob/683b401145d4a4c2bace49f356a5aa401fe81eb1/backend/src/test/java/org/tapiok/blogi/service/impl/PostServiceImplTest.java

Register your mock with Spring-ReInject before the application context starts in your test's constructor. 在应用程序上下文在测试的构造函数中开始之前,向Spring-ReInject注册您的模拟。 The original bean will be replaced with a mock, and the mock will be used by Spring everywhere, including injected fields. 原始的bean将被一个模拟代替,Spring将在所有地方(包括注入的字段)使用该模拟。 The original bean will be never created. 原始的bean将永远不会被创建。

There is an option to fake Spring bean with just plain Spring features. 有一个选项可以伪造仅具有纯Spring功能的Spring bean。 You need to use @Primary , @Profile and @ActiveProfiles annotations for it. 您需要使用@Primary@Profile@ActiveProfiles注解吧。

I wrote a blog post on the topic. 我写了一篇有关该主题的博客文章。

I've created the example to answer another question, but also cover your case. 我创建了该示例以回答另一个问题,但同时也介绍了您的情况。 Simple replace MockitoJUnitRunner via SpringJUnit4ClassRunner . 简单的更换MockitoJUnitRunner通过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. 简而言之,我创建了Java Spring Configuration,它仅包含应该测试/模拟的类,并返回模拟的对象而不是真正的对象,然后让Spring起作用。 Very simple and flexible solution. 非常简单灵活的解决方案。

It also works fine with MvcMock 它也可以与MvcMock一起MvcMock

从Spring Boot 1.4.x开始,您可以使用名为@MockBean的新注释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM