spring 3 自动装配和 junit 测试

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3660933/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 04:07:24  来源:igfitidea点击:

spring 3 autowiring and junit testing

springjunitautowired

提问by mike27

My code:

我的代码:

@Component
public class A {
    @Autowired
    private B b;

    public void method() {}
}

public interface X {...}

@Component
public class B implements X {
    ...
}

I want to test in isolation class A. Do I have to mock class B? If yes, how? Because it is autowired and there is no setter where i could send the mocked object.

我想在隔离类 A 中测试。我必须模拟 B 类吗?如果是,如何?因为它是自动装配的,并且没有可以发送模拟对象的设置器。

回答by earldouglas

I want to test in isolation class A.

我想在隔离级别 A 中进行测试。

You should absolutely mock B, rather than instantiate and inject an instance of B. The point is to test A whether or not B works, so you should not allow a potentially broken B interfere with the testing of A.

你应该完全模拟 B,而不是实例化和注入 B 的实例。重点是测试 A 是否 B 工作,所以你不应该让潜在的 B 干扰对 A 的测试。

That said, I highly recommend Mockito. As mocking frameworks go, it is extremely easy to use. You would write something like the following:

也就是说,我强烈推荐Mockito。随着模拟框架的发展,它非常易于使用。您将编写如下内容:

@Test
public void testA() {
    A a = new A();
    B b = Mockito.mock(B.class); // create a mock of B
    Mockito.when(b.getMeaningOfLife()).thenReturn(42); // define mocked behavior of b
    ReflectionTestUtils.setField(a, "b", b); // inject b into the B attribute of A

    a.method();

    // call whatever asserts you need here
}

回答by Mike Partridge

Here's an example of how I got my tests working with Spring 3.1, JUnit 4.7, and Mockito 1.9:

这是我如何使用 Spring 3.1、JUnit 4.7 和 Mockito 1.9 进行测试的示例:

FooService.java

服务类

public class FooService {
    @Autowired private FooDAO fooDAO;
    public Foo find(Long id) {
        return fooDAO.findById(id);
    }
}

FooDAO.java

FooDAO.java

public class FooDAO {
    public Foo findById(Long id) {
        /* implementation */
    }
}

FooServiceTest.java

服务测试.java

@RunWith(MockitoJUnitRunner.class)
public class FooServiceTest {
    @Mock private FooDAO mockFooDAO;
    @InjectMocks private FooService fooService = new FooService();

    @Test public final void findAll() {
        Foo foo = new Foo(1L);
        when(mockFooDAO.findById(foo.getId()).thenReturn(foo);

        Foo found = fooService.findById(foo.getId());
        assertEquals(foo, found);
    }
}

回答by Jeff Storey

You can inject the field via reflection using Spring's ReflectionTestUtils.setField(or the junit extension PrivateAccessor) or you can create a mock application context and load that. Though for a simple unit (non-integration) test, I favor using reflection for simplicity.

您可以使用 Spring 的ReflectionTestUtils.setField(或 junit 扩展PrivateAccessor)通过反射注入该字段,或者您可以创建一个模拟应用程序上下文并加载它。尽管对于一个简单的单元(非集成)测试,为了简单起见,我更喜欢使用反射。

回答by Aaron

This forum discussionmakes sense to me. You can declare your private member b as a type of InterfaceB which is implemented by the class B (ie: service-oriented) then declare a MockB class would also implement the same interface. In your test environment application context, you declare MockB class and your production application context you declare the normal B class and in either case, the code for class A does not need to be changed since it will be auto-wired.

这个论坛讨论对我来说很有意义。您可以将私有成员 b 声明为由类 B 实现的 InterfaceB 类型(即:面向服务),然后声明一个 MockB 类也将实现相同的接口。在您的测试环境应用程序上下文中,您声明 MockB 类,而您的生产应用程序上下文则声明普通 B 类,在任何一种情况下,A 类的代码都不需要更改,因为它将被自动连接。