PHP单元测试类,加载另一个类

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

PHP Unittest class that loads another class

问题

我有以下情况

class User 
{
  private $id;
  private $roleId;
  private $role;

  public function __construct(int $id, int $roleId)
  {
    $this->id = $id;
    $this->setRoleId($roleId);
  }

  public function setRoleId(int $roleId)
  {
    $this->role = Role::load($roleId);
  }
}

class Role
{
  public function __construct($x, $y ,$z)
  {
    //...
  }

  static function load(int $id) : Role
  {
    // 一些魔法代码
    return new Role($id);
  }

  public function getRoleId() : int
  {
    return $this->role->getId();
  }

  public function getRole() : Role
  {
    return $this->role;
  }
}

我的问题是,如何对User类进行单元测试?
Role类从Web服务中加载自身... 一个存根或模拟对象似乎不合适(我猜),因为要模拟的对象是Role,而我正在测试User类...

任何想法都欢迎

/BR

Philippe

英文:

I have the following situation

class User 
{
  private $id;
  private $roleId;
  private $role;

  public function __construct(int $id, int $roleId)
  {
    $this->id = $id;
    $this->setRoleId($roleId);
  }

  public function setRoleId(int $roleId)
  {
    $this->role = Role::load($roleId);
  }
}

class Role
{
  public function __construct($x, $y ,$z)
  {
    //...
  }

  static function load(int $id) : Role
  {
    // some magic code
    return new Role($id);
  }

  public function getRoleId() : int
  {
    return $this->role->getId();
  }

  public function getRole() : Role
  {
    return $this->role;
  }
}

My Problem is, how can I unittest the User-Class?
The Role Class loads itself from a webservice... A Stub or Mock is not suitable (I guess) because, the to-be-mocked-object is Role and I'm testing the User-Class here...

Any Idea is welcome

/BR

Philippe

答案1

得分: 0

Your User class here doesn't do anything except it loads Role. So the question is what would you unit test in this class?

Unit test purpose is to check if one method works as it should. It means if for defined inputs it returns expected results, or throw errors if inputs are not valid.

Stub or mock Role class is completely OK if you do unit testing. Imagine that you have the next method in User class (pseudo code I am not so good in PHP)

public function getUserRights() : String[]
{
String[] array = new String[5];
if ($this->role.equals('ADMIN')){
... some logic here ...
}

return array;
}

If now you stub your role and in different tests you return different Role from stubbed (mocked) object you can check that your method getUserRights() works properly based on different Roles.

And also it is OK to load Role from a webservice but in that case I would call that Integration tests and in that case you want to check if your webservice works correctly and setting those kinds of tests is not as easy as it is to do with unit tests.

英文:

Your User class here doesn't do anything except it loads Role. So the question is what would you unitest in this class?

Unit test purpose is to check if one method works as it should. It means if for defined inputs it returns expected results, or throw errors if inputs are not valid.

Stub or mock Role class is completely OK if you do unit testing. Imagine that you have next method in User class(pseudo code I am not so good in PHP)

public function getUserRights() : String[]
  {
    String[] array = new String[5];
    if ($this->role.equals('ADMIN'){
       
        .... some logic here ...
    }

    return array;
  }

If now you stub your role and in different tests you return different Role from stubbed(mocked) object you can check that your method getUserRights() works properly based on different Roles.

And also it is OK to loads Role from a webservice but in that case I would call that Integration tests and in that case you want to check if your webservice works correctly and setting those kind of tests is not as easy as it is to do with unit test.

答案2

得分: 0

在这种情况下,您正在让您的 User 类负责加载角色。通常,这不是 User 类的责任。相反,您可以在 User 类上定义一个名为 setRole(Role $role) 的函数,该函数接受一个真实的 Role 或者一个虚假/存根/模拟/任何 Role,而不是用户ID。然后,角色的检索是在实际使用用户对象的函数/代码中完成的。

但是,如何测试该类?

在单元测试中,通常最好不依赖于像 Role::load 这样的静态方法。相反,您可以使用非静态方法。然后,您可以编写一个扩展 Role 的类,在测试期间执行您想要的操作。然后,您还可以编写一些代码来检查是否已完成您告诉它要做的事情。

这就是为什么通常不建议使用许多静态方法:因为它们难以进行测试。

英文:

In this case you are making your User class responsible for loading the role. Typically that is not the responsibility of your User class. Instead, you could for example define a function setRole(Role $role) on your User class that accepts either a real Role, or a fake/stub/mock/whatever Role, instead of a user ID. The retrieving of the role is then done in the function/code that actually uses the user object.

But then how to test that class?

In unit testing it is usually easier not to depend on static methods like your Role::load one. Instead you could have a non-static method. Then you could write a class that extends Role, that does something that you want it to do during your tests. Then you can also write something that checks if what you told it to do was done.

That's why it is often discouraged to use many static methods: because it's hard to test (with) them.

huangapple
  • 本文由 发表于 2020年1月3日 21:30:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/59579476.html
匿名

发表评论

匿名网友

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

确定