jUnit如何测试仅从实体设置数据到数据传输对象的方法

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

jUnit how to test methods that only set data from entity to dto

问题

我有关于仅从实体获取数据并将其分配给DTO的测试方法的问题。我传递了一个空的DTO,并且由entityMother创建了一个实体。该方法运行正确,但我不知道如何对其进行断言。我认为为DTO的每个值/属性创建断言不是测试的正确方法。

为什么我需要测试这样的方法?

  • 设置从实体到DTO的数据的方法具有一些特定的格式化字段。比如分割字符串等。
@Test
public void shouldSetAvailabilities() {
    EditedTemplateShowDto editedTemplateDto = new EditedTemplateShowDto();
    productTemplateEditService.getAndSetAvailabilities(editedTemplateDto, editedProduct);

    //这里应该有一个条件来检查该方法是否设置了数据
}

我只需要检查该方法没有引发任何错误,并且没有任何字段被分配了空值。

英文:

I've problems with test methods which only get data from entity and assign it to DTO.
I passed empty DTO, and entity created by entityMother. The method works correctly, but I don't know how to make assertion for this. I think that creating assertion for each value/property of this DTO is not a right way to test it.

Why I need to test methods like this?

  • The methods that set data from entity to DTO has small formatting specyfic fields. Like splitting a string etc.
@Test
    public void shouldSetAvailabilities() {
        EditedTemplateShowDto editedTemplateDto = new EditedTemplateShowDto();
        productTemplateEditService.getAndSetAvailabilities(editedTemplateDto, editedProduct);

        //Here should be condition which check that the metod set data
    }

I just need to check that the method didn't throw any errors, and none of fields has assigned null value.

答案1

得分: 1

可能的解决方案是:

  • 您可以将对象序列化为JSON,然后比较生成的字符串。(最清晰的方法)
  • 覆盖匹配的toString(),然后比较生成的字符串。
  • 在测试中使用反射来放置多个断言条件(检查变量名),以检查是否存在任何空值或未映射的值(不良实践)。
英文:

The possible solutions are:

  • You may serialize your objects to JSON then compare the resulting strings. (Cleanest way)
  • Overriding a matching toString() then compare the resulting strings.
  • Put several assert condition using reflection (to check the variable name) in a test to check there are no any null value or not mapped value (Bad Practice).

答案2

得分: 1

> 为什么我需要测试这样的方法?

首先,您并不是一定要测试任何东西。如果您觉得代码非常简单,那么我建议您将时间投入到其他事情上。或者,您可以编写一个全面的测试,这样至少您就拥有了代码覆盖率(但在我看来,您这样做更多是为了统计数据,而不是为了产品的实际质量)。

> 我只需检查该方法是否抛出任何错误

这很简单!只需编写一个单元测试来调用该方法。如果该方法抛出任何异常,测试将失败。如果您希望使您的测试方法更具表达意图,您可以明确地编写如下:

try {
      productTemplateEditService.getAndSetAvailabilities(editedTemplateDto, editedProduct);
   } catch(Exception e) {
      fail("不应该抛出任何异常");
   }

但同样,我只会在我预期会抛出异常的方法上这样做(例如,因为它们具有异常路径或使用可能引发异常的其他代码/库)。任何单元测试的默认行为是在遇到未捕获的异常时失败。

> 没有字段被赋予了空值。

在您的测试方法中,JUnit 的方式是对您希望确保不为 null 的任何字段使用 assertNotNull

如果您希望采用更通用的方法,还有其他类库,比如 assertj 的 hasNoNullFieldsOrProperties

assertThat(editedTemplateDto).hasNoNullFieldsOrProperties();

或者您可以自己编写使用反射的代码,类似于:

for (Field f : editedTemplateDto.getClass().getDeclaredFields())
    assertNotNull(f.get(editedTemplateDto))

但我建议不要这样做,因为它会使您的测试代码难以理解(而且可能因为反射本身很棘手而变得脆弱)。

英文:

> Why I need to test methods like this?

First of all, you don't need to test anything. If you feel the code is extremely straight forward then I would advice to just invest your time into something else. Or perhaps write one sweeping test so at least you have code coverage (but IMO you'd be doing this more for the stats than actual quality of your product).

> I just need to check that the method didn't throw any errors

That's easy! Just write a unit test that calls the method. If the method throws any exceptions, the test will fail. If you want to make your test method more intent-revealing, you could explicitly write it like:

try {
      productTemplateEditService.getAndSetAvailabilities(editedTemplateDto, editedProduct);
   } catch(Exception e) {
      fail("Should not have thrown any exception");
   }

But again, I'd only do this with methods I expect to throw exceptions (e.g. because they have exception paths or use other code/libraries that may throw exceptions). The default behavior of any unit test is to fail when it encounters an uncaught exception.

> none of fields has assigned null value.

The JUnit way is to use assertNotNull in your test method on any fields you want to ensure are not null.

If you want a more generic approach there are additional libraries like assertj's hasNoNullFieldsOrProperties.

assertThat(editedTemplateDto).hasNoNullFieldsOrProperties();

Or you could write your own code using reflection like:

for (Field f : editedTemplateDto.getClass().getDeclaredFields())
    assertNotNull(f.get(editedTemplateDto))

But I'd advice against this as it makes your test code harder to understand (and possibly brittle because reflection itself can be tricky)

答案3

得分: 0

将实体中的数据设置到DTO的方法具有少量的格式化特定字段,比如拆分字符串等。

这使得单元测试变得有意义:验证DTO中的字段是否按预期填充。因此,不仅要测试notNull,还要测试以下内容:

Assert.assertEquals("FieldX的值不正确", "我期望的值", dto.getFieldX());

这样你可以测试拆分逻辑是否按预期工作。

还要测试所有可选字段中的null值,以验证是否会出现NullPointerException。

英文:

> The methods that set data from entity to DTO has small formatting
> specyfic fields. Like splitting a string etc.

This makes a unit test meaningful: verify if the fields in the DTO are filled as expected. So don't just test on notNull but test on

Assert.assertEquals("FieldX has a wrong value","myexpectedValue",dto.getFieldX());

This way you test if the split logic behaves as expected.

Also test it with null values in all optional fields to verify you don't get NullPointerException.

huangapple
  • 本文由 发表于 2020年8月24日 19:24:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/63560058.html
匿名

发表评论

匿名网友

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

确定