写单元测试时,我应该优先选择哪一个作为预期值?

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

When writing the unit test, which one should I prefer as the expected value?

问题

我正在开发一个项目。这个项目的主题是公司向用户发送消息。每家公司都有消息限制,当公司选择的语言超过消息限制时,系统会抛出一个异常。

我为这个异常编写了单元测试。

// 假设
Company company = new Company("Comp1", 2); // 构造函数(公司名称,语言)  2 -> EN
User user = new User("User1");
Email email = new Email("Email Test", "Test");
int emailLimit = company.getEmailLimit();

// 当
for (int i = 0; i < emailLimit; i++) {
     company.SendEmail(email, user);
}
Throwable throwable = catchThrowable(() -> company.SendEmail(email, user));

// 那么
assertThat(throwable).isInstanceOf(MessageLimitException.class);

我还想检查消息内容。

有一个名为“ErrorMessages”的类,用于管理错误消息的内容。

public class ErrorMessages {

   private static String[] messageLimitErrorMessage = {
        "Message Limit Error",   // 0 -> 默认
        "Mesaj limiti aşıldı",   // 1 -> TR
        "Message limit exceeded" // 2 -> EN
   };

   public static String messageLimitException(int languageIndex) {
        return messageLimitErrorMessage[languageIndex];
   };

}

作为预期值,我应该选择哪个?

// 选项 1
assertThat(throwable).hasMessage(ErrorMessages.messageLimitException(company.getLanguage()));

// 或者

// 选项 2
assertThat(throwable).hasMessage("Message limit exceeded");

两者都是正确的,但是为了测试的准确性,我应该选择选项 1 还是选项 2?

提前感谢您的回答。

英文:

I'm developing a project. The subject of this project, companies send message to users. Each company has a message limit and the system throws an exception based on the language chosen by the company when the message limit is exceeded.

I wrote unit test for the exception.

// given
Company company = new Company(&quot;Comp1&quot;, 2); // constructor (company name, language)  **  2 -&gt; EN
User user = new User(&quot;User1&quot;);
Email email = new Email(&quot;Email Test&quot;, &quot;Test&quot;);
int emailLimit = company.getEmailLimit();
    
// when
for (int i = 0; i &lt; emailLimit; i++) {
     company.SendEmail(email, user);
}
Throwable throwable = catchThrowable(() -&gt; company.SendEmail(email, user));

// then
assertThat(throwable).isInstanceOf(MessageLimitException.class);

I also want to check the message content.

There is a class named "ErrorMessages" that manages the content of the error message.

public class ErrorMessages {

   private static String[] messageLimitErrorMessage = {
        &quot;Message Limit Error&quot;,   // 0 -&gt; default
        &quot;Mesaj limiti aşıldı&quot;,   // 1 -&gt; TR
        &quot;Message limit exceeded&quot; // 2 -&gt; EN
   };

   public static String messageLimitException(int languageIndex) {
        return messageLimitErrorMessage[languageIndex];
   };

}

Which one should I prefer as the expected value?

// Option 1
assertThat(throwable).hasMessage(ErrorMessages.messageLimitException(company.getLanguage()));

// or

// Option 2
assertThat(throwable).hasMessage(&quot;Message limit exceeded&quot;);

Both are correct but which one should I prefer for the accuracy of the test, Option 1 or 2 ?

Thanks for your answer in advance.

答案1

得分: 2

对于这个问题,没有明确的答案。这取决于你想要实现什么目标。如果返回的确切错误消息很重要(例如规范的一部分),那么你应该选择选项2。如果你不想将消息硬编码到测试中(例如因为它可能会更改),那么你可以选择选项1。

一般来说,一个测试应该专注于它试图测试的一个特定方面。测试确切的错误消息可能在单独的单元测试中完成得更好(例如在那里你可以测试所有不同的消息)。就个人而言,我通常不会费心为错误消息编写测试,除非它们有一些特殊之处(例如在消息本身内部具有某种可变性)。你的时间有限,可能更好地用在其他地方。

你还应该考虑使用Java对国际化消息包的内置支持。它允许你在属性文件中保存特定于区域设置的消息,并为你加载这些消息。Java国际化消息包的文档可以帮助你了解更多信息。

英文:

There is no definitive answer to this question. It depends what you're trying to achieve. If the exact error message that is returned is important (e.g. part of the spec) then you should choose Option 2. If you don't want to hard code the message into the test (e.g. because it may change) then you can choose Option 1.

In general a test should focus on one specific thing that it's trying to test. Testing the exact error message might be better off done in a separate unit test (e.g. where you could test all of the different messages). Personally, I don't usually bother to write tests for error messages, unless there is something special about them (e.g. they have some kind of variability within the message itself). You only have so much time and it's probably better spent elsewhere.

You should also consider using Java's built-in support for internationalized message bundles. It lets you hold Locale-specific messages in properties files and loads them in for you.

答案2

得分: 0

"随着测试变得更加具体,代码变得更加通用。"

用非常具体的期望编写测试,将其与实现解耦,使代码随着时间的推移变得更加通用。

这应该告诉您,您可能应该使用选项2。

这里是Robert Martin对此的看法

英文:

"As the tests become more specific, the code becomes more generic."

Writing the test with a very specific expectation, decouples it from the implementation, and allows the code to become more generic over time.

This should tell you that you should probably use option 2.

Here's Robert Martin's take on it.

huangapple
  • 本文由 发表于 2020年9月20日 03:12:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/63972520.html
匿名

发表评论

匿名网友

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

确定