- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我今天才开始了解 Mockito。我写了一些简单的测试(使用 JUnit,见下文),但我不知道如何在 Spring 的托管 bean 中使用模拟对象。什么是使用 Spring 的最佳实践。我应该如何向我的 bean 注入(inject)模拟依赖项?
你可以跳过这个直到回到我的问题。
首先,我学到了什么。这是一篇很好的文章Mocks Aren't Stubs这解释了基础知识(Mock 的检查行为验证而不是状态验证)。那么这里有一个很好的例子Mockito 在这里Easier mocking with mockito .我们解释说 Mockito 的模拟对象既是 mock 又是 stub。
这里 Mockito在这里Matchers ,您可以找到更多示例。
这个测试
@Test
public void testReal(){
List<String> mockedList = mock(List.class);
//stubbing
//when(mockedList.get(0)).thenReturn("first");
mockedList.get(anyInt());
OngoingStubbing<String> stub= when(null);
stub.thenReturn("first");
//String res = mockedList.get(0);
//System.out.println(res);
//you can also verify using argument matcher
//verify(mockedList).get(anyInt());
verify(mockedList);
mockedList.get(anyInt());
}
工作得很好。
回到我的问题。 这里 Injecting Mockito mocks into a Spring bean有人尝试使用 Springs ReflectionTestUtils.setField()
,但这里是 Spring Integration Tests, Creating Mock Objects我们建议改变 Spring 的上下文。
我并没有真正理解最后两个链接...有人可以向我解释一下 Spring 对 Mockito 有什么问题吗?这个解决方案有什么问题?
@InjectMocks
private MyTestObject testObject
@Mock
private MyDependentObject mockedObject
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
https://stackoverflow.com/a/8742745/1137529
编辑:我不是很清楚。我将提供 3 个代码示例来澄清我自己:假设,我们有带有 printHello()
方法的 bean HelloWorld 和带有 sayHello
方法的 bean HelloFacade,它们将调用转发到 HelloWorld 的方法 printHello()
。
第一个例子是使用 Spring 的上下文并且没有自定义运行器,使用 ReflectionTestUtils 进行依赖注入(inject) (DI):
public class Hello1Test {
private ApplicationContext ctx;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
this.ctx = new ClassPathXmlApplicationContext("META-INF/spring/ServicesImplContext.xml");
}
@Test
public void testHelloFacade() {
HelloFacade obj = (HelloFacade) ctx.getBean(HelloFacadeImpl.class);
HelloWorld mock = mock(HelloWorld.class);
doNothing().when(mock).printHello();
ReflectionTestUtils.setField(obj, "hello", mock);
obj.sayHello();
verify(mock, times(1)).printHello();
}
}
正如@Noam 指出的那样,有一种方法可以在不显式调用 MockitoAnnotations.initMocks(this);
的情况下运行它。在这个示例中,我还将放弃使用 Spring 的上下文。
@RunWith(MockitoJUnitRunner.class)
public class Hello1aTest {
@InjectMocks
private HelloFacade obj = new HelloFacadeImpl();
@Mock
private HelloWorld mock;
@Test
public void testHelloFacade() {
doNothing().when(mock).printHello();
obj.sayHello();
}
}
另一种方法
public class Hello1aTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@InjectMocks
private HelloFacadeImpl obj;
@Mock
private HelloWorld mock;
@Test
public void testHelloFacade() {
doNothing().when(mock).printHello();
obj.sayHello();
}
}
不,在前面的示例中,我们必须手动实例化 HelloFacadeImpl 并将其分配给 HelloFacade,因为 HelloFacade 是接口(interface)。在最后一个示例中,我们可以只声明 HelloFacadeImpl,Mokito 将为我们实例化它。这种方法的缺点是,现在被测单元是 impl-class 而不是接口(interface)。
最佳答案
老实说,我不确定我是否真的理解你的问题:P 我会尽量澄清,从你原来的问题中得到的:
首先,在大多数情况下,您不应该对 Spring 有任何顾虑。您很少需要让 spring 参与编写单元测试。一般情况下,你只需要在你的单元测试中实例化被测系统(SUT,被测目标),并在测试中也注入(inject)SUT的依赖。依赖项通常是一个模拟/ stub 。
您最初建议的方式,示例 2、3 正是我上面描述的。
在极少数情况下(例如集成测试或一些特殊的单元测试),您需要创建一个 Spring 应用程序上下文,并从应用程序上下文中获取您的 SUT。在这种情况下,我相信您可以:
1) 在 spring app ctx 中创建您的 SUT,获取对其的引用,并向其注入(inject)模拟
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("test-app-ctx.xml")
public class FooTest {
@Autowired
@InjectMocks
TestTarget sut;
@Mock
Foo mockFoo;
@Before
/* Initialized mocks */
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test
public void someTest() {
// ....
}
}
或
2) 按照链接 Spring Integration Tests, Creating Mock Objects 中描述的方式进行操作.这种方法是在 Spring 的应用程序上下文中创建模拟,您可以从应用程序 ctx 中获取模拟对象来进行 stub /验证:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("test-app-ctx.xml")
public class FooTest {
@Autowired
TestTarget sut;
@Autowired
Foo mockFoo;
@Test
public void someTest() {
// ....
}
}
这两种方法都应该有效。主要区别在于前一种情况将在经过spring的生命周期等之后注入(inject)依赖项(例如bean初始化),而后一种情况是预先注入(inject)的。例如,如果您的 SUT 实现了 spring 的 InitializingBean,并且初始化例程涉及依赖项,您将看到这两种方法之间的区别。我相信这两种方法没有对错之分,只要你知道自己在做什么。
只是一个补充,@Mock、@Inject、MocktoJunitRunner 等在使用 Mockito 时都是不必要的。它们只是实用程序,可帮助您节省键入 Mockito.mock(Foo.class) 和一堆 setter 调用的时间。
关于java - Mockito、JUnit 和 Spring,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10906945/
我一直面临一个奇怪的问题。基本上,当我正常运行 Mockito 测试时,即“作为 Junit 测试运行”时,它给了我以下错误。有人可以帮助我请问我的错误是什么? 收到的错误: java.lan
我正在使用 Mockito 以及 mockito-inline用于模拟静态方法。我正在尝试申请 doNothing或类似的行为,到静态 void 方法。以下解决方法有效,但我认为应该有一种更方便的方法
我正在尝试验证我正在测试的类是否调用了正确的依赖类的方法。所以我试图匹配方法参数,但我并不真正关心这个测试中的实际值,因为我不想让我的测试变得脆弱。 但是,我在设置它时遇到了麻烦,因为 Mockito
我正在使用 Mockito 编写单元测试,并且在模拟注入(inject)的类时遇到问题。问题是两个注入(inject)的类是相同的类型,仅通过它们的 @Qualifier 注释进行区分。如果我尝试简单
在我的断言中的以下简单练习中,我期望 1,但得到 0。为什么我会看到这种行为? public class MockitoTest { POJO mockedPojo; @Before
我正在创建一个通用模拟客户端来测试 HTTP 交互。为此,我希望能够以相同的方法进行多次响应。使用普通模拟,这不是问题: when(mock.execute(any(), any(), any()))
我需要全局模拟类方法。 我的意思是,我不能创建模拟对象和 stub 方法。我的 api 不将此对象作为参数,所以我不能在函数调用中传递它,但是这个类的对象是在这些函数中创建并在那里使用的。这就是为什么
我正在尝试使用 Mockito 2.18.3 框架模拟我们公司内部库中提供的 final 类,不幸的是我们无权更改库中的代码。但每当我运行时,我都会收到以下错误: java.lang.NoClassD
研究了mockito测试框架,学习了powermock,突然发现一个叫powermockito的框架,看不懂了。 谁能告诉我这三个测试工具的区别? 最佳答案 Mockito 是市场标准模拟框架,味道非
我想跳过检查验证调用中的参数之一。因此对于: def allowMockitoVerify=Mockito.verify(msg,atLeastOnce()).handle(1st param,,3r
为了模拟在被测方法内部构造的本地对象上的局部变量/方法调用,我们目前使用的是 PowerMockito 库。 我们正在尝试评估是否可以使用 mockito-inline(版本 3.7.7)来做同样的事
我在想, 如果在 @Before 方法中我正在初始化模拟对象,我不应该在 @After 中取消对它的引用吗?或者那会是多余的吗?为什么? 最佳答案 不需要,JUnit 会为每个测试方法创建一个新的测试
我想使用 Mockito 验证字符串参数是否满足两个条件: verify(mockClass).doSomething(Matchers.startsWith("prefix")); verify(m
如果我像这样创建一个模拟 when(servicesTestEnv.mockUserProfileAndPortfolioTransactionRepository.get(servicesTestE
使用 Mockito 我遇到了以下问题: Mockito.when(restOperationMock.exchange( Mockito.anyString(), M
我想知道描述中的事情是否可行以及如何去做。 我知道你可以调用原始方法然后像这样做答案: when(presenter, "myMethod").doAnswer() 但我想对它们进行不同的排序,首先执
我试图弄清楚org.mockito.AdditionalMatchers是如何工作的,但我失败了。为什么这个测试失败了? import static org.hamcrest.CoreMatchers
有人知道使用 Mockito 为 ATG 编写单元测试用例吗?我在凝视时遇到了以下讨论 - Automated unit tests for ATG development和 Using PowerM
我想知道描述中的事情是否可行以及如何去做。 我知道你可以调用原始方法然后像这样做答案: when(presenter, "myMethod").doAnswer() 但我想对它们进行不同的排序,首先执
我有以下接口(interface)CatalogVersionService,它公开了一些服务。我还有一个单元测试,它通过使用 Mockito 来模拟这个接口(interface),如下所示: Cat
我是一名优秀的程序员,十分优秀!