简体   繁体   English

NestJs - 如何对 DTO 进行单元测试?

[英]NestJs - How to unit test a DTO?

I am asking you for help.我请你帮忙。 I have created a DTO that looks like it (this is a smaller version) :我创建了一个看起来像这样的 DTO(这是一个较小的版本):

export class OfImportDto {

    @IsString({
        message: "should be a valid product code"
    })
    productCode: string;

    @IsString({
        message: "Enter the proper product description"
    })
    productDescription: string;

    @IsDateString({
        message: "should be a valid date format, for example : 2017-06-07T14:34:08+04:00"
    })
    manufacturingDate : Date

    @IsInt({
        message: "should be a valid planned quantity number"
    })
    @IsPositive()
    plannedQuantity: number;

the thing is that i am asking to test that, with a unit test and not a E2E test.问题是我要求用单元测试而不是 E2E 测试来测试它。 And I Don't know how to do that.我不知道该怎么做。 For instance, I would like to unit test 1/ if my product code is well a string, a string should be created, if not, throw my exception 2/ if my product description is well a string, a string should be created, if not, throw my exception ... and so on.例如,我想进行单元测试 1/ 如果我的产品代码是一个字符串,则应该创建一个字符串,如果不是,则抛出我的异常 2/ 如果我的产品描述是一个字符串,则应该创建一个字符串,如果不,抛出我的异常......等等。

So, can I made a spec.ts file to test that?那么,我可以制作一个 spec.ts 文件来测试吗? If yes, how?如果是,如何? If not, is it better to test it within the service.spec.ts?如果没有,最好在 service.spec.ts 中测试它吗? If so, how?如果是这样,如何?

Thank you very much, any help would be very helpful :)非常感谢,任何帮助都会非常有帮助:)

It would be possible to create a OfImportDTO.spec.ts file (or whatever your original file is called), but the thing is, there isn't any logic here to test.可以创建一个OfImportDTO.spec.ts文件(或任何您调用的原始文件),但问题是,这里没有任何逻辑可以测试。 The closest thing you could do is create an instance of a Validator from class-validator and then instantiate an instance of the OfImportDto and then check that the class passes validation.您可以做的最接近的事情是从class-validator创建Validator的实例,然后实例化OfImportDto的实例,然后检查该类是否通过验证。 If you add logic to it (eg getters and setters with specific functions) then it could make sense for unit testing, but otherwise, this is basically an interface being called a class so it exists at runtime for class-validator如果向其中添加逻辑(例如具有特定功能的 getter 和 setter),那么它对单元测试可能有意义,但除此之外,这基本上是一个被称为类的接口,因此它在运行时存在于class-validator

You should create a separate DTO specific file like of-import.dto.spec.ts for unit tests of your DTOs.您应该为 DTO 的单元测试创​​建一个单独的 DTO 特定文件,例如of-import.dto.spec.ts Let's see how to test a DTO in Nest.js step by step.让我们一步一步地看看如何在 Nest.js 中测试 DTO。


TLDR: Your DTO's unit test TLDR:您的 DTO 的单元测试

To understand it line by line, continue reading:要逐行理解,请继续阅读:

it('should throw when the planned quantity is a negative number.', async () => {
  const importInfo = { productCode: 4567, plannedQuanity: -10 }
  const ofImportDto = plainToInstance(OfImportDto, importInfo)
  const errors = await validate(ofImportDto)
  expect(errors.length).not.toBe(0)
  expect(stringified(errors)).toContain(`Planned Quantity must be a positive number.`)
}

Create a plain object to test创建一个普通对象进行测试

The following is an object that you would like to test for validation:以下是您要测试以进行验证的对象:

const importInfo = { productCode: 4567, plannedQuanity: -10 }

If your test object has nested objects or it's too big, you can skip those complex properties.如果你的测试对象有嵌套对象或者它太大,你可以跳过那些复杂的属性。 We'll see how to deal with that.我们将看看如何处理。


Convert the test object to the type of DTO将测试对象转换为 DTO 的类型

Use plainToinstace() function from the class-transformer package:使用class-transformer包中的plainToinstace()函数:

const ofImportDto = plainToInstance(OfImportDto, importInfo)

This will turn your plain test object to the object of the type of your DTO, that is, OfImportDto .这会将您的普通测试对象转换为 DTO 类型的对象,即OfImportDto


Emulate the validation模拟验证

Use the validate() function from the class-validator package:使用class-validator包中的validate()函数:

const errors = await validate(ofImportDto)

If you skipped some properties while creating the test object, you can deal with that like the following:如果您在创建测试对象时跳过了某些属性,您可以像下面这样处理:

const errors = await validate(ofImportDto, { skipMissingProperties: true })

Now the validation will ignore the missing properties.现在验证将忽略缺少的属性。


Assert the errors断言错误

Assert that the errors array is not empty and it contains your custom error message:断言errors数组不为空并且它包含您的自定义错误消息:

expect(errors.length).not.toBe(0)
expect(stringified(errors)).toContain(`Planned Quantity must be a positive number.`)

Here stringified() is a helper function to convert the errors object to a JSON string, so we can search if it contains our custom error message:这里的stringified()是一个将errors对象转换为 JSON 字符串的辅助函数,因此我们可以搜索它是否包含我们的自定义错误消息:

export function stringified(errors: ValidationError[]): string {
  return JSON.stringify(errors)
}

That's it!而已! Hope that helps.希望有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM