英文:
How to mock a dependency for an @Autowire object?
问题
我有一个@Autowired对象,其中有一些字段的方法调用需要被模拟。
在主类中:
@Component
public class Pizza {
private Tomato tomato;
private Cheese cheese;
@Autowired
private Pizza(Tomato tomato, Cheese cheese) {
this.tomato = tomato;
this.cheese = cheese;
}
public String arrangePizza(Tomato tomato, Cheese cheese) {
Sauce sauce = tomato.createSauce();
combine(sauce, cheese);
return "Pizza created!";
}
}
在测试类中:
@RunWith(SpringRunner.class)
public class TestPizza {
@Autowired
private Pizza pizza;
// 可能在这里创建cheese和tomato的实例
private void testCreatePizza {
// 在这里我想要模拟tomato.createSauce()
pizza.arrangePizza(tomato, cheese);
}
}
我正在尝试使用Mockito或EasyMock来模拟testCreatePizza中的tomato.createSauce()方法,但我不确定在Pizza被@Autowired的情况下该如何操作。我是否需要在测试类中创建@Autowired实例的tomato和cheese?Spring会自动知道将构造函数设置为这些实例吗?
英文:
I have an @Autowire object, which has fields whose method calls need to be mocked.
In the main class:
@Component
public class Pizza {
private Tomato tomato;
private Cheese cheese;
@Autowired
private Pizza(Tomato tomato, Cheese cheese) {
this.tomato = tomato;
this.cheese = cheese;
}
public String arrangePizza(tomato, cheese) {
Sauce sauce = tomato.createSauce();
combine(sauce, cheese);
return "Pizza created!"
}
}
In the test class:
@RunWith(SpringRunner.class)
public class TestPizza {
@Autowire
private Pizza pizza;
//probably create instances of cheese and tomato here?
private void testCreatePizza {
//here I want to mock tomato.createSauce()
pizza.arrangePizza(tomato, cheese);
}
}
I am trying to mock the method tomato.createSauce() in testCreatePizza using Mockito or EasyMock, but I'm not sure how to do this given that Pizza is Autowired. Would I have to create Autowire instances of tomato
and cheese
in the test class? Would spring automatically know to set the constructor to those instances?
答案1
得分: 1
Mockito提供了`@Mock`注解来模拟对象,以及`@InjectMocks`注解来将这些模拟对象注入到自动装配的字段中。
@RunWith(SpringRunner.class)
@ExtendWith(MockitoExtension.class)
public class TestPizza {
@Mock
private Tomato tomato;
@Mock
private Cheese cheese;
@InjectMocks
private Pizza pizza;
@BeforeEach
void init() {
MockitoAnnotations.initMocks(this);
when(tomato.createSauce()).thenReturn("辣酱");
}
@Test
private void testCreatePizza {
pizza.createPizza(tomato, cheese);
}
}
英文:
Mockito provides the @Mock
annotation to mock an object and @InjectMocks
annotation to inject those mocks into an autowired field.
@RunWith(SpringRunner.class)
@ExtendWith(MockitoExtension.class)
public class TestPizza {
@Mock
private Tomato tomato;
@Mock
private Cheese cheese;
@InjectMocks
private Pizza pizza;
@BeforeEach
void init() {
MockitoAnnotations.initMocks(this);
when(tomato.createSauce()).thenReturn("Spicy Sauce");
}
@Test
private void testCreatePizza {
pizza.createPizza(tomato, cheese);
}
}
答案2
得分: 1
因为这被标记为spring-boot,所以值得指出@MockBean注解。 (相关引用:“上下文中定义的任何现有的相同类型的单个bean都将被模拟对象替换。如果没有现有的bean被定义,将添加一个新的bean。”)
这意味着在你的测试类中,你可以这样做:
@Autowired
private Pizza pizza;
@MockBean
private Tomato tomato;
然后像往常一样使用Mockito的when
等方法。与另一个答案相比,这种方式可以节省一个或两个注解(如果你要模拟多个对象),以及一个调用initMocks()的操作。
英文:
Since this is tagged spring-boot, it's worth also pointing out the @MockBean annotation. (Relevant quote: "Any existing single bean of the same type defined in the context will be replaced by the mock. If no existing bean is defined a new one will be added.")
That means that, in your test class, you can do
@Autowired
private Pizza pizza;
@MockBean
private Tomato tomato;
and then use Mockito's when
and so on the way you usually do. Compared to the other answer, this way saves you an annotation or two (if you're mocking multiple things), as well as a call to initMocks().
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论