简体   繁体   English

Junit:局部变量和void方法

[英]Junit: local variables and void methods

I'm fairly new to unit testing and have been reading a lot of material online, but I'm having a little trouble figuring stuff out. 我对单元测试还很陌生,并且已经在线阅读了很多材料,但是在弄清内容方面有些麻烦。

For example: If I have the following piece of code : 例如:如果我有以下代码:

public class RandomClass
{
  int a = 4;
  public void foo(Object obj)
  {
    if(a == 4)
    {
      AnotherObject anotherObj = new AnotherObject();
      anotherObj.setAttribute(obj.getFiled());
      //Method call that will be suppressed 
      Anotherclass.anotherMethod(anotherObj);
    } 
  }
}

I thought of writing my junit test case like this: 我想到写这样的junit测试用例:

@Test
public void testFoo()
{
  int a=4;
  RandomClass randomClass = new RandomClass();
  Object object = new Object();
  object.setField("hey");
  randomClass.foo(object);
}

I have a couple of questions here. 我在这里有几个问题。 How exactly do I set the integer a from my junit? 我如何从我的junit设置整数a? The way I'm setting it right now doesn't the unit test case any impact. 我现在设置的方式不会对单元测试用例产生任何影响。 When I debug the unit test, the value of a is NULL so it never passes the if condition! 当我调试单元测试时,a的值为NULL,因此它永远不会通过if条件!

Also, the method foo returns a void so what can I possibly test/assert? 另外,方法foo返回一个void,所以我可能会测试/声明什么?

There are two major techniques when writing unit tests: 编写单元测试时,有两种主要技术:

  1. Checking the external contract of your class under test. 检查被测课程的外部合同。 Meaning: you try to write testcases for RandomClass that know nothing about AnotherClass . 含义:您尝试编写测试用例RandomClass一无所知 AnotherClass。 Instead, your test code only observes behavior of RandomClass objects. 而是,您的测试代码仅观察RandomClass对象的行为。 In other words: you really don't care about the internal implementation details of RandomClass - because all the things you "want to see" can be observed by checking what RandomClass objects return when you call methods with specific parameters. 换句话说:您实际上并不在乎RandomClass的内部实现细节-因为您可以通过检查在调用具有特定参数的方法时返回的RandomClass对象返回来观察所有“想要看到的东西”。 Occasionally you get there by adding (package protected) getter methods that allow you to inspect some internal state of your class under test. 有时候,您可以通过添加(受程序包保护的)getter方法到达那里,该方法允许您检查被测类的某些内部状态。
  2. But sometimes that might not be "good enough"; 但是有时候这可能还不够“好”。 for example when you know that your class under test must be using some other objects to get its job done. 例如,当您知道被测类必须使用其他对象才能完成其工作时。 In such situations, you should be looking into mocking objects. 在这种情况下,您应该研究模拟对象。 In your case, you might want to create a mocked instance of AnotherClass ; 在您的情况下,您可能想要创建AnotherClass的模拟实例; and then you would use dependency injection in order to provide that object to your class under test. 然后您将使用依赖注入以将该对象提供给您的受测类。

You see, you actually wrote "hard to test" code - because you are calling new for AnotherClass in your production code. 您会看到,您实际上编写了“难以测试”的代码-因为您在生产代码中为AnotherClass调用了new That doesn't seem like a big deal, but depending on what AnotherClass is about ... you really shouldn't do that! 这似乎没什么大不了,但是取决于AnotherClass是关于什么的……您真的不应该这样做!

In any case; 任何状况之下; I recommend you to look into these videos to learn how to write code that works better for unit testing. 我建议您观看这些视频,以学习如何编写更适合单元测试的代码。

A test normally starts with a "setup", "prepare", or "arrange" step, where it creates or modifies the object under test so that it is in the state needed by that particular test. 测试通常从“设置”,“准备”或“安排”步骤开始,在该步骤中,将创建或修改被测对象,使其处于该特定测试所需的状态。

So, if field a in the RandomClass object needs to have a value 4 (for example), then the test needs to either create the object passing this value as a constructor argument, or to set the value in the object by calling a setter method or by directly accessing the field. 因此,如果RandomClass对象中的字段a需要具有值4 (例如),则测试需要创建将该值作为构造函数参数传递的对象, 或者通过调用setter方法在该对象中设置值或直接访问该字段。 In the worst case, you might need to use Reflection to set the field, but that would indicate a design issue in the class being tested. 在最坏的情况下,您可能需要使用Reflection来设置字段,但这将指示正在测试的类中存在设计问题。

The next step is to exercise the code under test. 下一步是测试代码。 This is the "act" step, in the "Arrange, Act, Assert" terminology (AAA, for short). 这是“安排,行动,声明”术语(简称AAA)中的“行动”步骤。

Finally, the final step is to "assert" (verify) the code being tested did what is was supposed to do. 最后,最后一步是“声明”(验证)所测试的代码是否按照预期执行。

If the method being tested has void return type, then the test should verify it did what was expected either through state verification or through behavior verification. 如果所测试的方法具有void返回类型,则测试应通过状态验证或行为验证来验证其是否达到了预期的效果。

In the first case, the test would call some getter method in the object under test, and use it in an "assert" of some kind (for example, an assertEquals(expectedValue, actualValue) ). 在第一种情况下,测试将在被测对象中调用某种getter方法,并将其用于某种类型的“断言”(例如assertEquals(expectedValue, actualValue) )。

In the second case, the test would use some mocking library in order to verify that expected calls were made from the code under test to one or more dependencies (other objects or classes on which the class under test depends). 在第二种情况下,测试将使用一些模拟库,以验证预期的调用是从被测代码对一个或多个依赖项(被测类所依赖的其他对象或类)进行的。 For example, here the test could verify that RandomClass#foo did actually call Anotherclass.anotherMethod(...) . 例如,这里的测试可以验证RandomClass#foo是否确实调用了Anotherclass.anotherMethod(...)

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

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