我有一个控制器
@RestController
public class Create {
@Autowired
private ComponentThatDoesSomething something;
@RequestMapping("/greeting")
public String call() {
something.updateCounter();
return "Hello World " + something.getCounter();
}
}
我有一个该控制器的组件
@Component
public class ComponentThatDoesSomething {
private int counter = 0;
public void updateCounter () {
counter++;
}
public int getCounter() {
return counter;
}
}
我也对我的控制器进行了测试。
@RunWith(SpringRunner.class)
@SpringBootTest
public class ForumsApplicationTests {
@Test
public void contextLoads() {
Create subject = new Create();
subject.call();
subject.call();
assertEquals(subject.call(), "Hello World 2");
}
}
当控制器调用something.updateCounter()
时,测试失败。我得到NullPointerException
。虽然我理解可以将@Autowired
添加到构造函数中,但我想知道是否仍然使用@Autowired
字段执行此操作。如何确保@Autowired
字段注释在我的测试中有效?
答案 0 :(得分:3)
Spring没有自动连接你的组件导致你用 new 实例化你的Controller而不是Spring,所以Component没有实现
SpringMockMvc测试检查是否正确:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class CreateTest {
@Autowired
private WebApplicationContext context;
private MockMvc mvc;
@Before
public void setup() {
mvc = MockMvcBuilders
.webAppContextSetup(context)
.build();
}
@Test
public void testCall() throws Exception {
//increment first time
this.mvc.perform(get("/greeting"))
.andExpect(status().isOk());
//increment secont time and get response to check
String contentAsString = this.mvc.perform(get("/greeting"))
.andExpect(status().isOk()).andReturn()
.getResponse().getContentAsString();
assertEquals("Hello World 2", contentAsString);
}
}
答案 1 :(得分:1)
使用Mockito并注入您创建的模拟。我更喜欢构造函数注入:
@RestController
public class Create {
private ComponentThatDoesSomething something;
@Autowired
public Create(ComponentThatDoesSomething c) {
this.something = c;
}
}
不要在Junit测试中使用Spring。
public CreateTest {
private Create create;
@Before
public void setUp() {
ComponentThatDoesSomething c = Mockito.mock(ComponentThatDoesSomething .class);
this.create = new Create(c);
}
}
答案 2 :(得分:1)
使用正确的注释,可以使用MockitoJUnitRunner轻松模拟和测试@Autowired类。
通过这个,你可以做任何你需要做的单元测试的模拟对象。
这是一个快速示例,它将使用ComponentThatDoesSomething中的模拟数据测试Create方法调用。
@RunWith(MockitoJUnitRunner.class)
public class CreateTest {
@InjectMocks
Create create;
@Mock
ComponentThatDoesSomething componentThatDoesSomething;
@Test
public void testCallWithCounterOf4() {
when(componentThatDoesSomething.getCounter()).thenReturn(4);
String result = create.call();
assertEquals("Hello World 4", result);
}
}