使用PHPUnit

时间:2015-10-03 23:05:52

标签: php phpunit composer-php

当我尝试测试这个类时,使用PSR-4自动加载Composer:

namespace User;

use User\Contracts\UserId;
use User\Contracts\User as UserContract;

class User implements UserContract
{
    private $id;

    public function __construct(UserId $id)
    {
        $this->id = $id;
    }

    public function getId()
    {
        return $this->id;
    }
}

使用PHPUnit:

use User\Contracts\UserId;

class UserTest extends \PHPUnit_Framework_TestCase
{
    public function test_the_identifier_can_be_used_as_string()
    {
        $identifier = m::mock(UserId::class);
        $identifier->shouldReceive('__toString')->once()->andReturn('foo');

        $user = new User($identifier);

        $this->assertSame('foo', (string) $user->getId());
    }
}

我在控制台中收到此错误

PHP Fatal error:  Cannot use User\Contracts\UserId as UserId because the name is already in use in /src/User/User.php on line 5

这是文件/文件夹结构:

src
`-- User
    |-- Contracts
    |    |-- User.php
    |    `-- UserId.php
    |-- User.php
    `-- UserId.php
tests
`-- User
    |-- UserIdTest.php
    `-- UserTest.php

我已就这些问题进行了大量搜索,但我没有找到任何解决方法。

  • PHP版本:5.6.13-1 + deb.sury.org~trusty + 3
  • PHPUnit版本:5.0.3
  • 操作系统:Ubuntu 14.04.3 LTS

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:5)

您无法将类导入已使用相同别名在其中声明的命名空间。

您有\User\UserId并希望将\User\Contracts\UserId导入\User命名空间。这会使快捷方式UserId变得暧昧。

http://php.net/manual/en/language.namespaces.importing.php#117334

您可以在导入时使用别名,也可以直接使用相对路径:

namespace User;

class User implements Contracts\User
{
    private $id;

    public function __construct(Contracts\UserId $id) {}
}

更新2018-03-20:

有一个错误报告https://bugs.php.net/bug.php?id=66773,如果在没有操作码缓存的情况下使用,则会抱怨PHP触发此错误,但不是。原因是使用opcache编译是按文件完成的,并且合理的期望是仅考虑文件的内容。但是,似乎错误是导入“冲突”类时,先前加载的文件中的现有类定义会受到影响。

它以正确的方式修复了PHP 7.0.13:每个单独的文件只能解释自己,如果你想导入一个类并用它的简写名称来使用它,你可以这样做而不管其他任何类可能存在于命名空间中。您只是松开了对这些类的访问 - 这是无关紧要的,因为您的代码首先不使用它们。如果您想要更改,则必须更改导入。

由于opcache通常在命令行上被禁用,因此在使用PHPUnit时可能会触发此错误。

答案 1 :(得分:2)

尝试以下方法:

    public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolderCheese> {

    private LayoutInflater layoutInflater;
    private static ClickListener clickListener;
    private ArrayList<Person> arrayList = new ArrayList<>();

    public void setArrayList(ArrayList<Person> arrayList) {
        this.arrayList = arrayList;
        notifyDataSetChanged();
    }

    public RecyclerViewAdapter(Context context) {
        this.layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public ViewHolderCheese onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = layoutInflater.inflate(R.layout.item_list, viewGroup, false);
        return new ViewHolderCheese(view);
    }

    @Override
    public void onBindViewHolder(ViewHolderCheese viewHolderCheese, int i) {
        final Person s = arrayList.get(i);
        if (s.getName() != null) {
            viewHolderCheese.textView_t.setText(s.getName());
            viewHolderCheese.phone.setText(s.getPhone());

            if (s.getPicture_path() != null) {
                Glide.with(viewHolderCheese.picture.getContext())
                        .load(s.getPicture_path())
                        .fitCenter()
                        .diskCacheStrategy(DiskCacheStrategy.NONE)
                        .skipMemoryCache(true)
                        .into(viewHolderCheese.picture);
            } else {
                final ColorGenerator generator = ColorGenerator.MATERIAL;
                final int color = generator.getRandomColor();
                final String letter = s.getName().substring(0, 1);
                TextDrawable drawable = TextDrawable.builder()
                        .buildRect(letter, color);
                viewHolderCheese.picture.setImageDrawable(drawable);
            }
        }
    }

    public void setClickListener(ClickListener clickListener) {
        RecyclerViewAdapter.clickListener = clickListener;
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    public static class ViewHolderCheese extends RecyclerView.ViewHolder implements View.OnClickListener {

        TextView textView_t;
        TextView phone;
        ImageView picture;

        public ViewHolderCheese(View itemView) {
            super(itemView);
            textView_t = (TextView) itemView.findViewById(R.id.textview);
            phone = (TextView) itemView.findViewById(R.id.phone);
            picture = (ImageView) itemView.findViewById(R.id.image);

            itemView.setOnClickListener(this);
        }

        @Override
        public void onClick(View view) {
            if (clickListener != null) {
                clickListener.itemClick(view, getAdapterPosition());
            }
        }
    }

    public interface ClickListener {
        void itemClick(View v, int position);
    }
}

可能是因为你正在进行命名冲突

use User\Contracts\UserId as UserIdContract;

User 类的同一名称空间中也有 UserId

因此...

use User\Contracts\UserId;

希望它有所帮助!