简体   繁体   English

如果类没有setter,如何将对象自动连接到bean

[英]How to autowire object to bean if class does not have setter

I have so controller 我有控制器

@Controller
public class MyController {
 @Autowire
 MyClass myClass;
 //myClass doesn't have setter and getter
 .... 
 @RequestMapping("/path")
 public String underTest(){
    myClass.makeSomething();
    return "html.jsp"
}

I want make mock test using Mockito and mock myClass. 我想使用Mockito和模拟myClass进行模拟测试。 In test class I want get myClass so: 在测试类中,我想获取myClass:

ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/BeanConfig.xml"); 
myClass = context.getBean("myClass ", MyClass .class);

But I need autowire this bean to Controller for testing controller's method(I think test code should not affect to normal code). 但是我需要将这个bean自动连接到Controller来测试控制器的方法(我认为测试代码不应影响正常代码)。

There are exist way to make it without writing of set method? 有没有写set方法的方法来制作它?

I want to check that myClass.makeSomething() invokes once in method underTest. 我想检查myClass.makeSomething()是否在方法underTest中调用一次。

As long as your test for MyController resides in the same package as MyController itself (as it's usually done - same packages in different source folders), you can simply assign it: 只要您对MyController的测试与MyController本身位于同一个程序包中(通常已完成-在不同的源文件夹中包含相同的程序包),您就可以简单地为其分配:

MyController controller = new MyController();
controller.myClass = mockMyClass;

That's the reason not to put @Inject / @Autowired on private fields. 这就是不将@Inject / @Autowired放在private字段上的原因。

Try testing the controller directly with context.getBean(). 尝试直接使用context.getBean()测试控制器。 MyClass will be autowired into it. MyClass将自动连接到其中。

I'm not sure I agree with you that test code should not affect normal code. 我不确定我是否同意测试代码不会影响正常代码。 I think an entirely valid reason to refactor / rewrite production code is to make it more testable (this is probably achieved by making it more modular, which is generally a good thing anyway). 我认为重构/重写生产代码的一个完全正当的理由是使其更具可测试性(这可能是通过使其具有更高的模块化性来实现的,无论如何这通常是一件好事)。

This is precisely why annotations like 这就是为什么注释之类的

@VisibleForTesting

exist. 存在。 Then you can create a package-local setter for MyClass, add the above annotation (for information to other programmers and possibly code inspection tools) and set the field in your test (which should reside in the same package). 然后,您可以为MyClass创建一个程序包本地的setter,添加上面的注释(以供其他程序员和可能的代码检查工具参考),并在测试中设置字段(应位于同一程序包中)。

Alternatively, since you are using Mockito, you could simply annotate the MyController instance with @InjectMocks, eg 另外,由于您使用的是Mockito,因此可以使用@InjectMocks注释MyController实例,例如

@Test
public class MyControllerTest {

    @Mock
    private MyClass mockMyClass;
    @InjectMocks
    private MyController myController;

    @BeforeMethod
    public void before() {
        MockitoAnnotations.initMocks(this);
    }

    // do tests...
}

Note that @InjectMocks does not depend on any annotations on the target field (ie @Autowired, @Resource, @Inject etc). 请注意,@ InjectMocks不依赖于目标字段上的任何注释(即,@ Autowired,@ Resource,@ Inject等)。 It just works. 它只是工作。 (Presumably you will still need those annotations for Spring injection, so don't remove them! The point is you can also use it for fields that aren't annotated). (大概对于Spring注入,您仍然需要这些注释,所以不要删除它们!关键是您还可以将其用于未注释的字段)。

Note also that, depending on which version of Mockito you are using, you may need to instantiate the MyController in the before() method before calling MockitoAnnotations.initMocks() 还要注意,根据所使用的Mockito版本,您可能需要在调用MockitoAnnotations.initMocks()之前在before()方法中实例化MyController。

I agree with @axtavt's answer, however if you absolutely want to go your way with injecting the mock in an integration test, you can do this: 我同意@axtavt的回答,但是,如果您绝对想在集成测试中注入模拟,可以这样做:

define a overriding bean configuration file, say bean-test-config.xml, with content along these lines: 定义一个覆盖的bean配置文件,例如bean-test-config.xml,其内容如下:

<import resource="classpath:spring/BeanConfig.xml"/>
<bean name="myClass" factory-method="mock" class="org.mockito.Mockito">
 <constructor-arg value="MyClass"></constructor-arg>
</bean>

This should correctly inject in a mock in your controller. 这应该正确地注入控制器中的模拟中。 You will have to get hold of this mock in your test and inject in any behavior that you are expecting from this mock though. 但是,您必须在测试中掌握此模拟,并注入您希望从该模拟获得的任何行为。

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

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