【问题标题】:AssertionError: Status expected:<201> but was:<400> JUnit POST MethodAssertionError: Status expected:<201> but was:<400> JUnit POST Method
【发布时间】:2022-01-23 04:22:03
【问题描述】:

尝试启动 JUnit 测试时出现错误。当我调用该方法时,我收到错误“java.lang.AssertionError: Status expected: but was:”。

我做错了什么? URL是对的,程序运行正常,但是测试没有通过。

我的控制器:

@RestController
@RequestMapping(value = "addresses", produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class AddressController {

    private final AddressService addressService;


    @GetMapping("/{id}")
    public AddressResponse getAddress(@PathVariable Integer id) {
        return addressService.getAddress(id)
                .map(AddressResponse::convertToResponse)
                .orElse(null);
    }

    @GetMapping
    public List<AddressResponse> getAllAddresses() {
        return addressService.getAllAddresses()
                .stream()
                .map(AddressResponse::convertToResponse)
                .collect(Collectors.toList());
    }

    @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
    public AddressResponse createAddress(@RequestBody AddressRequest request) {
        return AddressResponse.convertToResponse(addressService.upsertAddress(request));
    }

    @PutMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
    public AddressResponse updateAddress(@RequestBody AddressRequest request) {
        return AddressResponse.convertToResponse(addressService.upsertAddress(request));
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public Address deleteAddress(@PathVariable Integer id) {
        return addressService.deleteAddress(id);
    }

我的服务:

@Service
@RequiredArgsConstructor
public class AddressService {

    private final AddressRepository addressRepository;


    public Optional<Address> getAddress(Integer id) {
        return addressRepository.findById(id);
    }

    public List<Address> getAllAddresses() {
        return addressRepository.findAll();
    }


    public Address upsertAddress(@NonNull AddressRequest addressRequest) {


        Address entity;

        if (addressRequest.getId() == null) {
            entity = new Address();
        } else {
            entity = addressRepository.findById(addressRequest.getId())
                    .orElseThrow(() -> new RuntimeException("Cannot find address by id"));
        }

        entity.setCity(addressRequest.getCity());
        entity.setStreet(addressRequest.getStreet());
        entity.setHouse(addressRequest.getHouse());

        entity = addressRepository.save(entity);

        return entity;
    }

    public Address deleteAddress(Integer id) {

        Address address = null;
        Optional<Address> optional = addressRepository.findById(id);

        if (optional.isPresent()) {
            address = optional.get();
            addressRepository.deleteById(id);
        }
        return address;
    }

}

}

还有我的测试班:

@ExtendWith(MockitoExtension.class)
class AddressControllerTest {

    @Mock
    private AddressService addressService;
    private com.second_bank.entities.Address address;
    private List<Address> addressList;

    @InjectMocks
    private AddressController addressController;

    @Autowired
    MockMvc mockMvc;

    @BeforeEach
    public void setup() {
        com.second_bank.entities.Address address = new com.second_bank.entities.Address("City", "Street", "House");
        mockMvc = MockMvcBuilders.standaloneSetup(addressController).build();
    }

    @AfterEach
    public void tearDown() {
        address = null;
        addressList = null;
    }

 
   

    @Test
    void createAddress() throws Exception {

        when(addressService.upsertAddress(any())).thenReturn(address);

        mockMvc.perform(post("/addresses")
                .contentType(MediaType.APPLICATION_JSON)
                .content(asJsonString(address)))
                .andExpect(status().isCreated());
        verify(addressService, times(1)).upsertAddress(any());
    }

我创建了一个将对象转换为 JSON 的方法

public static String asJsonString(final Object obj) {
        try {
            return new ObjectMapper().writeValueAsString(obj);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

DTO 响应:

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class AddressResponse {

    private Integer id;
    private String city;
    private String street;
    private String house;

    public static AddressResponse convertToResponse(Address address){

        return new AddressResponse(
                address.getId(),
                address.getCity(),
                address.getStreet(),
                address.getHouse()
        );
    }
}

DTO Request:

@Data
@JsonIgnoreProperties(ignoreUnknown = true)
public class AddressRequest {

    private Integer Id;
    private String city;
    private String street;
    private String house;


}

【问题讨论】:

  • 您的Address DTO 是什么样的?它有什么限制吗?您是否有一个全局异常处理程序来处理 400 个错误请求生成异常,以便您可以追查到真正的原因?
  • 添加到描述中

标签: java spring spring-boot junit mockito


【解决方案1】:

不确定这是否是问题所在,但您似乎期望正文中有一个 AddressRequest 对象,但您在测试中发送了一个 Address 对象。如果 JSON 转换为对象失败,则可能返回 400 错误。

【讨论】:

  • 看起来AddressAddressRequestAddressResponse 在结构上是相等的。似乎 OP 需要首先记录原因异常(据我所知,可以通过在 Spring 中使用全局建议进行异常处理来轻松完成;或者通过启用更多“神奇”属性来记录该信息;或者可能会降低日志记录严重性级别,以便记录 Spring TRACE/DEBUG 并找到错误。)
猜你喜欢
  • 2020-09-13
  • 1970-01-01
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 1970-01-01
  • 2020-09-02
  • 1970-01-01
  • 2023-03-05
相关资源
最近更新 更多