如何为一个使用了 @Autowire 的对象模拟一个依赖?

huangapple go评论69阅读模式
英文:

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().

huangapple
  • 本文由 发表于 2020年9月8日 08:11:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/63785593.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定