- 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/
本着this question from JUnit 3 to JUnit 4的精神, 是否有任何正则表达式列表到 有效地从 junit 4 API 迁移到 junit 5 API ,不管代码大小?
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
我需要以下测试 @runwith(cache, memory) class CollectionA is -- this is a suite (aka folder) class Cache {
当尝试在JUNITTEST的内存数据库中使用derby时,出现以下异常。 java.sql.SQLNonTransientConnectionException: Database 'memory:t
我需要以下测试 @runwith(cache, memory) class CollectionA is -- this is a suite (aka folder) class Cache {
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: How to run Junit testcases from command line? 如何在 Linu
可以将 Junitperf 与 junit4 一起使用吗?我有一个带有多个测试的简单 Junit4 测试类,我想对该类的单个测试进行 TimedTest。我该怎么做? 更清楚地说,我的 Junit4
我想将 JUnit 4 测试添加到使用 JUnit 3 测试套件(“AllTests”)来组织测试的遗留项目中。 测试已经用 JUnit 4 执行了,所以我知道 JUnit 4 测试在原则上是有效的。
我正在将我的代码库从 junit4 迁移到 junit5。我在我的测试用例中使用了 mockito。下面是我用于依赖项的不同版本。 5.2.0 1.2.0 1.10.19 or
我刚刚使用 qunit-reporter-junit 生成了以下 XML: 但是当我运行它时,我在以下位置找到了 xsd:http
我已经编写了一个自定义 JUnit 运行器,我希望它成为 eclipse 插件的一部分,该插件将使用该运行器启动测试,而无需将 @RunWith 注释应用于该类。我已经设法使用 org.eclipse
我发现我的Sonar实例5.1或5.1.1(带有最新的声纳运行器2.x)停止在项目的仪表板上显示部分单元测试信息(单元测试小部件)。 我拥有的属性是(在Gradle的sonarRunner> sona
我有一个 JUnit 测试。但是当我使用“Run as -> JUnit”时它会成功,而当我使用“Cover as -> JUnit”时它会失败。这是为什么?代码确实有问题。在代码中,我使用了一些遗留
这个问题在这里已经有了答案: How to test code dependent on environment variables using JUnit? (20 个答案) 关闭 8 年前。 我
当我们的临时服务器因每周维护而停机时,我们有许多集成测试失败。当临时服务器关闭时,我们会发送一个特定的响应,我可以在集成测试中检测到该响应。当我得到这个响应而不是测试失败时,我想知道是否可以跳过/忽略
我需要测试一个程序,它首先预处理一些数据,然后使用这些预处理过的数据计算几个不同的结果——为每个计算编写单独的测试是有意义的。 官方 JUnit 政策似乎是我应该在每次计算测试之前运行预处理。 我如何
JUnit 是否可以为每个测试方法添加描述文本,以便描述文本稍后出现在surefire/failsave xml 报告中!? 背景:我在受监管的环境中工作,必须编写大量文档、测试规范和测试报告。 JU
当 JUnit 中的断言失败时,我想做一些“自己的事情”。我想要这个: public class MyAssert extends org.junit.Assert { // @Overrid
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 8年前关闭。 Improve this q
我想将参数从运行配置传递给我的 JUnit 测试。我如何到达 JUnits 的主要方法来访问这些参数?有谁知道如何做到这一点? 谢谢 最佳答案 您可以使用 -D 系统属性运行单元测试,并使用 Syst
我是一名优秀的程序员,十分优秀!